...
37
.gitignore
vendored
@ -4,4 +4,39 @@
|
||||
node_modules
|
||||
logs/
|
||||
dist/
|
||||
tests_output/
|
||||
tests_output/
|
||||
node_modules
|
||||
.env
|
||||
coverage
|
||||
coverage.json
|
||||
typechain
|
||||
typechain-types
|
||||
|
||||
# Hardhat files
|
||||
cache
|
||||
artifacts
|
||||
|
||||
|
||||
node_modules
|
||||
.env
|
||||
coverage
|
||||
coverage.json
|
||||
typechain
|
||||
typechain-types
|
||||
|
||||
# Hardhat files
|
||||
cache
|
||||
artifacts
|
||||
|
||||
|
||||
node_modules
|
||||
.env
|
||||
coverage
|
||||
coverage.json
|
||||
typechain
|
||||
typechain-types
|
||||
|
||||
# Hardhat files
|
||||
cache
|
||||
artifacts
|
||||
|
||||
|
29
README.md
@ -1,24 +1,13 @@
|
||||
# gamesns
|
||||
# Sample Hardhat Project
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a script that deploys that contract.
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
Try running some of the following tasks:
|
||||
|
||||
### Compiles and minifies for production
|
||||
```shell
|
||||
npx hardhat help
|
||||
npx hardhat test
|
||||
REPORT_GAS=true npx hardhat test
|
||||
npx hardhat node
|
||||
npx hardhat run scripts/deploy.js
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
|
2
components.d.ts
vendored
@ -14,6 +14,8 @@ declare module '@vue/runtime-core' {
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SmallTag: typeof import('./src/components/SmallTag.vue')['default']
|
||||
TestView: typeof import('./src/components/TestView.vue')['default']
|
||||
TestViewO: typeof import('./src/components/TestViewO.vue')['default']
|
||||
UserCard: typeof import('./src/components/UserCard.vue')['default']
|
||||
}
|
||||
}
|
||||
|
34
contracts/Lock.sol
Normal file
@ -0,0 +1,34 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.9;
|
||||
|
||||
// Uncomment this line to use console.log
|
||||
// import "hardhat/console.sol";
|
||||
|
||||
contract Lock {
|
||||
uint public unlockTime;
|
||||
address payable public owner;
|
||||
|
||||
event Withdrawal(uint amount, uint when);
|
||||
|
||||
constructor(uint _unlockTime) payable {
|
||||
require(
|
||||
block.timestamp < _unlockTime,
|
||||
"Unlock time should be in the future"
|
||||
);
|
||||
|
||||
unlockTime = _unlockTime;
|
||||
owner = payable(msg.sender);
|
||||
}
|
||||
|
||||
function withdraw() public {
|
||||
// Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal
|
||||
// console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp);
|
||||
|
||||
require(block.timestamp >= unlockTime, "You can't withdraw yet");
|
||||
require(msg.sender == owner, "You aren't the owner");
|
||||
|
||||
emit Withdrawal(address(this).balance, block.timestamp);
|
||||
|
||||
owner.transfer(address(this).balance);
|
||||
}
|
||||
}
|
0
docs/test.drawio
Normal file
6
hardhat.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
require("@nomicfoundation/hardhat-toolbox");
|
||||
|
||||
/** @type import('hardhat/config').HardhatUserConfig */
|
||||
module.exports = {
|
||||
solidity: "0.8.17",
|
||||
};
|
3529
package-lock.json
generated
@ -33,6 +33,7 @@
|
||||
"pinia": "^2.0.23",
|
||||
"process": "^0.11.10",
|
||||
"style-resources-loader": "^1.5.0",
|
||||
"swiper": "^9.0.3",
|
||||
"util": "^0.12.5",
|
||||
"vue": "^3.2.13",
|
||||
"vue-router": "^4.1.6",
|
||||
@ -42,6 +43,7 @@
|
||||
"@emotion/is-prop-valid": "^1.2.0",
|
||||
"@esbuild-plugins/node-globals-polyfill": "^0.1.1",
|
||||
"@nightwatch/vue": "^0.4.1",
|
||||
"@nomicfoundation/hardhat-toolbox": "^2.0.1",
|
||||
"@rollup/plugin-alias": "^4.0.2",
|
||||
"@vitejs/plugin-vue": "^3.2.0",
|
||||
"browserify-zlib": "^0.2.0",
|
||||
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
BIN
public/images/hero_bg.png
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
public/images/service1.webp
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
public/images/swiper/desktop/5-1.jpg
Normal file
After Width: | Height: | Size: 270 KiB |
BIN
public/images/swiper/desktop/5-2.jpg
Normal file
After Width: | Height: | Size: 316 KiB |
BIN
public/images/swiper/desktop/5-3.jpg
Normal file
After Width: | Height: | Size: 283 KiB |
BIN
public/images/swiper/desktop/5-4.jpg
Normal file
After Width: | Height: | Size: 261 KiB |
BIN
public/images/swiper/desktop/5-kv1.jpg
Normal file
After Width: | Height: | Size: 275 KiB |
BIN
public/images/swiper/mobile/5-1.jpg
Normal file
After Width: | Height: | Size: 211 KiB |
BIN
public/images/swiper/mobile/5-2.jpg
Normal file
After Width: | Height: | Size: 247 KiB |
BIN
public/images/swiper/mobile/5-3.jpg
Normal file
After Width: | Height: | Size: 216 KiB |
BIN
public/images/swiper/mobile/5-4.jpg
Normal file
After Width: | Height: | Size: 209 KiB |
BIN
public/images/swiper/mobile/5-kv1.jpg
Normal file
After Width: | Height: | Size: 190 KiB |
31
scripts/deploy.js
Normal file
@ -0,0 +1,31 @@
|
||||
// We require the Hardhat Runtime Environment explicitly here. This is optional
|
||||
// but useful for running the script in a standalone fashion through `node <script>`.
|
||||
//
|
||||
// You can also run a script with `npx hardhat run <script>`. If you do that, Hardhat
|
||||
// will compile your contracts, add the Hardhat Runtime Environment's members to the
|
||||
// global scope, and execute the script.
|
||||
const hre = require("hardhat");
|
||||
|
||||
async function main() {
|
||||
const currentTimestampInSeconds = Math.round(Date.now() / 1000);
|
||||
const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60;
|
||||
const unlockTime = currentTimestampInSeconds + ONE_YEAR_IN_SECS;
|
||||
|
||||
const lockedAmount = hre.ethers.utils.parseEther("1");
|
||||
|
||||
const Lock = await hre.ethers.getContractFactory("Lock");
|
||||
const lock = await Lock.deploy(unlockTime, { value: lockedAmount });
|
||||
|
||||
await lock.deployed();
|
||||
|
||||
console.log(
|
||||
`Lock with 1 ETH and unlock timestamp ${unlockTime} deployed to ${lock.address}`
|
||||
);
|
||||
}
|
||||
|
||||
// We recommend this pattern to be able to use async/await everywhere
|
||||
// and properly handle errors.
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
33
src/App.vue
@ -10,12 +10,14 @@
|
||||
<a-menu-item key="/users">Users</a-menu-item>
|
||||
</a-menu>
|
||||
</a-col>
|
||||
<a-button type="primary" @click="login">{{ chain.logined ? "Logout" : "Login" }}</a-button>
|
||||
<a-avatar v-if="chain.logined" class="headpic" :src="getMyUserInfo().headpic" shape="circle" @click="showUserProfile"/>
|
||||
<a-button v-else type="primary" @click="login">Login</a-button>
|
||||
</a-row>
|
||||
<chain-model></chain-model>
|
||||
</a-layout-header>
|
||||
<a-layout-content :style="{ padding: '0px', marginTop: '64px' }">
|
||||
<router-view/>
|
||||
<a-drawer placement="right" :closable="false" :visible="visableDrawer" @close="onCloseDrawer"></a-drawer>
|
||||
</a-layout-content>
|
||||
<a-layout-footer>
|
||||
footer
|
||||
@ -26,12 +28,17 @@
|
||||
|
||||
<script setup>
|
||||
|
||||
import { ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useChainStore } from '@/store/chain';
|
||||
import { useAppStore } from '@/store/app';
|
||||
|
||||
import ChainModel from '@/components/ChainModel'
|
||||
|
||||
const router = useRouter();
|
||||
const chain = useChainStore();
|
||||
const app = useAppStore();
|
||||
const visableDrawer = ref(false);
|
||||
|
||||
function click(event) {
|
||||
router.push(event.key);
|
||||
@ -53,6 +60,25 @@ async function login(event) {
|
||||
}
|
||||
}
|
||||
|
||||
function getMyUserInfo() {
|
||||
const info = app.get(app.accountId);
|
||||
|
||||
if (!info) {
|
||||
return {
|
||||
head_pic: ""
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
async function showUserProfile(event) {
|
||||
visableDrawer.value = true;
|
||||
}
|
||||
|
||||
function onCloseDrawer(event) {
|
||||
visableDrawer.value = false;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang=less>
|
||||
@ -60,11 +86,6 @@ async function login(event) {
|
||||
@import 'ant-design-vue/dist/antd.dark.less';
|
||||
@import './css/main.less';
|
||||
|
||||
@font-face {
|
||||
font-family: Poppins;
|
||||
src: url(./assets/fonts/Poppins-Bold.ttf);
|
||||
}
|
||||
|
||||
.ant-menu {
|
||||
font-size: 1.5vmax;
|
||||
}
|
||||
|
@ -1,9 +1,34 @@
|
||||
<template>
|
||||
<div>
|
||||
GPalMenuItem<br/>
|
||||
ffaa
|
||||
</div>
|
||||
<div class="main">
|
||||
<img src="/images/service1.webp"/>
|
||||
<div class="content">
|
||||
League of Legends<br/>
|
||||
10% OFF<br/>
|
||||
1.80 2.00/Game
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.main {
|
||||
padding: 0.8vmax;
|
||||
display: flex;
|
||||
font-size: 1.2vmax;
|
||||
line-height: 2vmax;
|
||||
}
|
||||
.content {
|
||||
padding-left: 1vmax;
|
||||
display: block;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 4vmax;
|
||||
height: 4vmax;
|
||||
border-radius: 0.8vmax;
|
||||
display: block;
|
||||
}
|
||||
|
||||
</style>
|
131
src/components/TestView.vue
Normal file
@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<div class="big_hero">
|
||||
<swiper
|
||||
@swiper="setHeroSwiper"
|
||||
:slides-per-view="1"
|
||||
:thumbs="{ swiper: heroThumbsSwiper }"
|
||||
:modules="modules"
|
||||
:navigation="{ nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }"
|
||||
@slideChange="onSlideChange"
|
||||
>
|
||||
<SwiperSlide v-for="(slideContent, index) in heroList" :key="index">
|
||||
<img class="hero_big_image" :src="slideContent.img"/>
|
||||
</SwiperSlide>
|
||||
</swiper>
|
||||
</div>
|
||||
<div class="thumbs_hero_container">
|
||||
<Swiper
|
||||
@swiper="setHeroThumbsSwiper"
|
||||
|
||||
:slides-per-view="4"
|
||||
:modules="modules"
|
||||
class="HeroThumbs"
|
||||
:slideToClickedSlide="true"
|
||||
:centeredSlidesBounds="true"
|
||||
:multipleActiveThumbs="false"
|
||||
>
|
||||
<SwiperSlide v-for="(slideContent, index) in heroList" :key="index">
|
||||
<div class="hero_thumb">
|
||||
<img class="hero_thumb_img" :src="slideContent.img"/>
|
||||
<img v-if="test(index, slideContent)" class="hero_thumb_bg" src="/images/hero_bg.png"/>
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
<div class="swiper-button-prev"></div>
|
||||
<div class="swiper-button-next"></div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { Thumbs, FreeMode, Navigation } from 'swiper';
|
||||
import { Swiper, SwiperSlide } from 'swiper/vue';
|
||||
import 'swiper/css';
|
||||
import 'swiper/css/navigation';
|
||||
import 'swiper/css/thumbs';
|
||||
import 'swiper/css/free-mode';
|
||||
|
||||
const heroList = ref([
|
||||
{ id:1, img:location.origin+'/images/v1.jpg' },
|
||||
{ id:2, img:location.origin+'/images/v2.jpg' },
|
||||
{ id:3, img:location.origin+'/images/v3.jpg' },
|
||||
{ id:4, img:location.origin+'/images/v4.jpg' },
|
||||
{ id:5, img:location.origin+'/images/v5.jpg' },
|
||||
{ id:6, img:location.origin+'/images/v1.jpg' },
|
||||
]);
|
||||
|
||||
const modules = [FreeMode, Navigation, Thumbs];
|
||||
const heroSwiper = ref(null);
|
||||
const heroThumbsSwiper = ref(null);
|
||||
const activeIndex = ref(0);
|
||||
|
||||
const setHeroThumbsSwiper = (swiper) => {
|
||||
heroThumbsSwiper.value = swiper;
|
||||
console.log("setHeroThumbsSwiper ", swiper);
|
||||
// swiper.on('slideChange', function() {
|
||||
// console.log('slide changed', swiper);
|
||||
// activeIndex.value = swiper.activeIndex;
|
||||
// })
|
||||
}
|
||||
|
||||
const setHeroSwiper = (swiper) => {
|
||||
heroSwiper.value = swiper;
|
||||
}
|
||||
|
||||
const onSlideChange = () => {
|
||||
activeIndex.value = heroSwiper.value.activeIndex;
|
||||
}
|
||||
|
||||
function test(index, sc) {
|
||||
console.log(index,'oo');
|
||||
return activeIndex.value == index;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.big_hero {
|
||||
width:400px;
|
||||
height:400px;
|
||||
}
|
||||
.hero_big_image {
|
||||
width:400px;
|
||||
height:400px;
|
||||
}
|
||||
.thumbs_hero_container {
|
||||
user-select: none;
|
||||
position: relative;
|
||||
padding: 0 40px;
|
||||
width: 820px;
|
||||
height: 200px;
|
||||
}
|
||||
.hero_thumb {
|
||||
width: 200px;
|
||||
height:200px;
|
||||
}
|
||||
.hero_thumb_img {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 100px;
|
||||
top: 100px;
|
||||
width:160px;
|
||||
height:160px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.hero_thumb_bg {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width:200px;
|
||||
height:200px;
|
||||
}
|
||||
|
||||
.HeroThumbs {
|
||||
.swiper-button-prev {
|
||||
}
|
||||
.swiper-button-next {
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
131
src/components/TestViewO.vue
Normal file
@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<div class="big_hero">
|
||||
<swiper
|
||||
@swiper="setHeroSwiper"
|
||||
:slides-per-view="1"
|
||||
:thumbs="{ swiper: heroThumbsSwiper }"
|
||||
:modules="modules"
|
||||
:navigation="{ nextEl: '.swiper-button-nexto', prevEl: '.swiper-button-prevo', }"
|
||||
@slideChange="onSlideChange"
|
||||
>
|
||||
<SwiperSlide v-for="(slideContent, index) in heroList" :key="index">
|
||||
<img class="hero_big_image" :src="slideContent.img"/>
|
||||
</SwiperSlide>
|
||||
</swiper>
|
||||
</div>
|
||||
<div class="thumbs_hero_container">
|
||||
<Swiper
|
||||
@swiper="setHeroThumbsSwiper"
|
||||
|
||||
:slides-per-view="4"
|
||||
:modules="modules"
|
||||
class="HeroThumbs"
|
||||
:slideToClickedSlide="true"
|
||||
:centeredSlidesBounds="true"
|
||||
:multipleActiveThumbs="false"
|
||||
>
|
||||
<SwiperSlide v-for="(slideContent, index) in heroList" :key="index">
|
||||
<div class="hero_thumb">
|
||||
<img class="hero_thumb_img" :src="slideContent.img"/>
|
||||
<img v-if="test(index, slideContent)" class="hero_thumb_bg" src="/images/hero_bg.png"/>
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
<div class="swiper-button-prevo">&le</div>
|
||||
<div class="swiper-button-nexto">&lg</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { Thumbs, FreeMode, Navigation } from 'swiper';
|
||||
import { Swiper, SwiperSlide } from 'swiper/vue';
|
||||
import 'swiper/css';
|
||||
import 'swiper/css/navigation';
|
||||
import 'swiper/css/thumbs';
|
||||
import 'swiper/css/free-mode';
|
||||
|
||||
const heroList = ref([
|
||||
{ id:1, img:location.origin+'/images/v1.jpg' },
|
||||
{ id:2, img:location.origin+'/images/v2.jpg' },
|
||||
{ id:3, img:location.origin+'/images/v3.jpg' },
|
||||
{ id:4, img:location.origin+'/images/v4.jpg' },
|
||||
{ id:5, img:location.origin+'/images/v5.jpg' },
|
||||
{ id:6, img:location.origin+'/images/v1.jpg' },
|
||||
]);
|
||||
|
||||
const modules = [FreeMode, Navigation, Thumbs];
|
||||
const heroSwiper = ref(null);
|
||||
const heroThumbsSwiper = ref(null);
|
||||
const activeIndex = ref(0);
|
||||
|
||||
const setHeroThumbsSwiper = (swiper) => {
|
||||
heroThumbsSwiper.value = swiper;
|
||||
console.log("setHeroThumbsSwiper ", swiper);
|
||||
// swiper.on('slideChange', function() {
|
||||
// console.log('slide changed', swiper);
|
||||
// activeIndex.value = swiper.activeIndex;
|
||||
// })
|
||||
}
|
||||
|
||||
const setHeroSwiper = (swiper) => {
|
||||
heroSwiper.value = swiper;
|
||||
}
|
||||
|
||||
const onSlideChange = () => {
|
||||
activeIndex.value = heroSwiper.value.activeIndex;
|
||||
}
|
||||
|
||||
function test(index, sc) {
|
||||
console.log(index,'oo');
|
||||
return activeIndex.value == index;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.big_hero {
|
||||
width:400px;
|
||||
height:400px;
|
||||
}
|
||||
.hero_big_image {
|
||||
width:400px;
|
||||
height:400px;
|
||||
}
|
||||
.thumbs_hero_container {
|
||||
user-select: none;
|
||||
position: relative;
|
||||
padding: 0 40px;
|
||||
width: 820px;
|
||||
height: 200px;
|
||||
}
|
||||
.hero_thumb {
|
||||
width: 200px;
|
||||
height:200px;
|
||||
}
|
||||
.hero_thumb_img {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 100px;
|
||||
top: 100px;
|
||||
width:160px;
|
||||
height:160px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.hero_thumb_bg {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width:200px;
|
||||
height:200px;
|
||||
}
|
||||
|
||||
.HeroThumbs {
|
||||
.swiper-button-prevo {
|
||||
}
|
||||
.swiper-button-nexto {
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
@ -1,3 +0,0 @@
|
||||
.ant-menu-dark .ant-menu-item-selected {
|
||||
color: #FFF;
|
||||
}
|
@ -350,7 +350,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: Poppins;
|
||||
src: url(./assets/fonts/Poppins-Bold.ttf);
|
||||
src: url(../assets/fonts/Poppins-Bold.ttf);
|
||||
}
|
||||
|
||||
.ant-layout-sider {
|
||||
@ -376,7 +376,8 @@
|
||||
.gpal-menu-item {
|
||||
height: auto !important;
|
||||
color:white;
|
||||
border-radius: 12px;
|
||||
border-radius: 1vmax;
|
||||
padding: 0.2vmax !important;
|
||||
}
|
||||
.gpal-menu-item:hover {
|
||||
background-color:var(--color-surface-nest-hover);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { createApp } from 'vue';
|
||||
import Antd from 'ant-design-vue'
|
||||
// import 'ant-design-vue/dist/antd.less'
|
||||
import 'ant-design-vue/dist/antd.dark.less';
|
||||
import 'ant-design-vue/dist/antd.less'
|
||||
// import 'ant-design-vue/dist/antd.dark.less';
|
||||
// import 'ant-design-vue/dist/antd.variable.less';
|
||||
import 'animate.css';
|
||||
import './css/main.less';
|
||||
@ -19,8 +19,8 @@ window.Buffer = Buffer;
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const app = createApp(App)
|
||||
.use(pinia)
|
||||
.use(router)
|
||||
.use(pinia)
|
||||
.use(Antd)
|
||||
.use(MotionPlugin)
|
||||
.mount('#app');
|
||||
|
@ -9,7 +9,8 @@ const routes = [
|
||||
},
|
||||
{
|
||||
path: '/users',
|
||||
component: () => import(/* webpackChunkName "users" */ '../views/UserView.vue'),
|
||||
name: 'users',
|
||||
component: () => import('@/views/UserView.vue'),
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
@ -18,6 +19,14 @@ const routes = [
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue'),
|
||||
},
|
||||
{
|
||||
path: '/test',
|
||||
component: () => import('@/views/TestView.vue'),
|
||||
},
|
||||
{
|
||||
path: '/test2',
|
||||
component: () => import('@/views/TestView2.vue'),
|
||||
},
|
||||
{
|
||||
path: '/user/:id',
|
||||
name: 'user',
|
||||
|
@ -4,7 +4,7 @@ import { ref } from 'vue';
|
||||
export const useAppStore = defineStore('app', () => {
|
||||
|
||||
const list = ref([
|
||||
{userId: "1", headpic: "/images/1667520250923113.webp"},
|
||||
{userId: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", headpic: "/images/1667520250923113.webp"},
|
||||
{userId: "2", headpic: "/images/16555781459976085.webp"},
|
||||
{userId: "3", headpic: "/images/16595363622946259.webp"},
|
||||
{userId: "4", headpic: "/images/16620693455819353.webp"},
|
||||
|
246
src/views/TestView.vue
Normal file
@ -0,0 +1,246 @@
|
||||
<template>
|
||||
|
||||
<div class="box" ref="box" style="perspective:400px">
|
||||
<div>{{tilt}}x{{roll}}:{{boxStyle}}</div>
|
||||
<div class="thumbs_hero_container" :style="boxStyle1">
|
||||
<Swiper
|
||||
@swiper="setHeroThumbsSwiper"
|
||||
|
||||
:slides-per-view="4"
|
||||
:modules="modules"
|
||||
class="HeroThumbs"
|
||||
:slideToClickedSlide="true"
|
||||
:centeredSlidesBounds="true"
|
||||
:multipleActiveThumbs="false"
|
||||
:loop="true"
|
||||
>
|
||||
<SwiperSlide v-for="(slideContent, index) in heroList" :key="index">
|
||||
<div class="hero_thumb">
|
||||
<img class="hero_thumb_img" :src="slideContent.img"/>
|
||||
<img v-if="test(index, slideContent)" class="hero_thumb_bg" src="/images/hero_bg.png"/>
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
<div class="swiper-button-prev"></div>
|
||||
<div class="swiper-button-next"></div>
|
||||
|
||||
<button>
|
||||
<span>PLAY NOW</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="big_hero" :style="boxStyle4">
|
||||
<swiper
|
||||
@swiper="setHeroSwiper"
|
||||
:effect="'coverflow'"
|
||||
:slides-per-view="'2'"
|
||||
:thumbs="{ swiper: heroThumbsSwiper }"
|
||||
:modules="modules"
|
||||
:navigation="{ nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }"
|
||||
@slideChange="onSlideChange"
|
||||
:pagination="true"
|
||||
:loop="true"
|
||||
:centeredSlides="true"
|
||||
:coverflowEffect="{
|
||||
rotate: 0,
|
||||
stretch: 60,
|
||||
depth: 100,
|
||||
modifier: 3,
|
||||
slideShadows: true,
|
||||
scale: 0.80
|
||||
}"
|
||||
>
|
||||
<SwiperSlide v-for="(slideContent, index) in heroList" :key="index">
|
||||
<img class="hero_big_image" :src="slideContent.img"/>
|
||||
</SwiperSlide>
|
||||
</swiper>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { EffectCoverflow, Thumbs, FreeMode, Navigation } from 'swiper';
|
||||
import { Swiper, SwiperSlide } from 'swiper/vue';
|
||||
import { useParallax } from '@vueuse/core';
|
||||
|
||||
import 'swiper/css';
|
||||
import 'swiper/css/navigation';
|
||||
import 'swiper/css/thumbs';
|
||||
import 'swiper/css/free-mode';
|
||||
import 'swiper/css/effect-coverflow';
|
||||
|
||||
|
||||
const heroList = ref([
|
||||
{ id:1, img:location.origin+'/images/swiper/desktop/5-kv1.jpg' },
|
||||
{ id:2, img:location.origin+'/images/swiper/desktop/5-1.jpg' },
|
||||
{ id:3, img:location.origin+'/images/swiper/desktop/5-2.jpg' },
|
||||
{ id:4, img:location.origin+'/images/swiper/desktop/5-3.jpg' },
|
||||
{ id:5, img:location.origin+'/images/swiper/desktop/5-4.jpg' },
|
||||
]);
|
||||
|
||||
const modules = [FreeMode, Navigation, Thumbs, EffectCoverflow];
|
||||
const heroSwiper = ref(null);
|
||||
const heroThumbsSwiper = ref(null);
|
||||
const activeIndex = ref(0);
|
||||
|
||||
const box = ref(null);
|
||||
const { tilt, roll, source } = useParallax(box);
|
||||
|
||||
console.log(tilt, 'tilt');
|
||||
console.log(roll, 'roll');
|
||||
|
||||
const boxStyle1 = computed(()=>({
|
||||
perspective: '300px',
|
||||
transition: '.2s',
|
||||
transform: `translateX(${tilt.value * 10}px) translateY(${-roll.value * 10}px) rotateY(${tilt.value*5}deg) rotateX(${roll.value*5}deg)`
|
||||
}));
|
||||
const boxStyle2 = computed(()=>({
|
||||
perspective: '300px',
|
||||
transition: '.2s',
|
||||
transform: `translateX(${tilt.value * 20}px) translateY(${-roll.value * 20}px) rotateY(${tilt.value*5}deg) rotateX(${roll.value*5}deg)`
|
||||
}));
|
||||
const boxStyle3 = computed(()=>({
|
||||
perspective: '300px',
|
||||
transition: '.2s',
|
||||
transform: `translateX(${tilt.value * 30}px) translateY(${-roll.value * 30}px) rotateY(${tilt.value*5}deg) rotateX(${roll.value*5}deg)`
|
||||
}));
|
||||
const boxStyle4 = computed(()=>({
|
||||
perspective: '300px',
|
||||
transition: '.2s',
|
||||
transform: `translateX(${tilt.value * 40}px) translateY(${-roll.value * 40}px) rotateY(${tilt.value*5}deg) rotateX(${roll.value*5}deg)`
|
||||
}));
|
||||
|
||||
const setHeroThumbsSwiper = (swiper) => {
|
||||
heroThumbsSwiper.value = swiper;
|
||||
console.log("setHeroThumbsSwiper ", swiper);
|
||||
// swiper.on('slideChange', function() {
|
||||
// console.log('slide changed', swiper);
|
||||
// activeIndex.value = swiper.activeIndex;
|
||||
// })
|
||||
}
|
||||
|
||||
const setHeroSwiper = (swiper) => {
|
||||
heroSwiper.value = swiper;
|
||||
}
|
||||
|
||||
const onSlideChange = () => {
|
||||
activeIndex.value = heroSwiper.value?.activeIndex;
|
||||
}
|
||||
|
||||
function test(index, sc) {
|
||||
console.log(index,'oo');
|
||||
return activeIndex.value == index;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.big_hero {
|
||||
width:100%;
|
||||
height:400px;
|
||||
}
|
||||
.hero_big_image {
|
||||
width:970px;
|
||||
height:545px;
|
||||
}
|
||||
.thumbs_hero_container {
|
||||
user-select: none;
|
||||
position: relative;
|
||||
padding: 0 40px;
|
||||
width: 820px;
|
||||
height: 200px;
|
||||
}
|
||||
.hero_thumb {
|
||||
width: 200px;
|
||||
height:200px;
|
||||
}
|
||||
.hero_thumb_img {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 100px;
|
||||
top: 100px;
|
||||
width:160px;
|
||||
height:160px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.hero_thumb_bg {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width:200px;
|
||||
height:200px;
|
||||
}
|
||||
|
||||
.HeroThumbs {
|
||||
.swiper-button-prev {
|
||||
}
|
||||
.swiper-button-next {
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 73px;
|
||||
padding: 0;
|
||||
z-index: 2;
|
||||
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='868' width='2500' viewBox='0 0 726 252.17'%3E%3Cpath d='M483.92 0S481.38 24.71 466 40.11c-11.74 11.74-24.09 12.66-40.26 15.07-9.42 1.41-29.7 3.77-34.81-.79-2.37-2.11-3-21-3.22-27.62-.21-6.92-1.36-16.52-2.82-18-.75 3.06-2.49 11.53-3.09 13.61S378.49 34.3 378 36a85.13 85.13 0 0 0-30.09 0c-.46-1.67-3.17-11.48-3.77-13.56s-2.34-10.55-3.09-13.61c-1.45 1.45-2.61 11.05-2.82 18-.21 6.67-.84 25.51-3.22 27.62-5.11 4.56-25.38 2.2-34.8.79-16.16-2.47-28.51-3.39-40.21-15.13C244.57 24.71 242 0 242 0H0s69.52 22.74 97.52 68.59c16.56 27.11 14.14 58.49 9.92 74.73C170 140 221.46 140 273 158.57c69.23 24.93 83.2 76.19 90 93.6 6.77-17.41 20.75-68.67 90-93.6 51.54-18.56 103-18.59 165.56-15.25-4.21-16.24-6.63-47.62 9.93-74.73C656.43 22.74 726 0 726 0z'/%3E%3C/svg%3E") no-repeat 50% 50%;
|
||||
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='868' width='2500' viewBox='0 0 726 252.17'%3E%3Cpath d='M483.92 0S481.38 24.71 466 40.11c-11.74 11.74-24.09 12.66-40.26 15.07-9.42 1.41-29.7 3.77-34.81-.79-2.37-2.11-3-21-3.22-27.62-.21-6.92-1.36-16.52-2.82-18-.75 3.06-2.49 11.53-3.09 13.61S378.49 34.3 378 36a85.13 85.13 0 0 0-30.09 0c-.46-1.67-3.17-11.48-3.77-13.56s-2.34-10.55-3.09-13.61c-1.45 1.45-2.61 11.05-2.82 18-.21 6.67-.84 25.51-3.22 27.62-5.11 4.56-25.38 2.2-34.8.79-16.16-2.47-28.51-3.39-40.21-15.13C244.57 24.71 242 0 242 0H0s69.52 22.74 97.52 68.59c16.56 27.11 14.14 58.49 9.92 74.73C170 140 221.46 140 273 158.57c69.23 24.93 83.2 76.19 90 93.6 6.77-17.41 20.75-68.67 90-93.6 51.54-18.56 103-18.59 165.56-15.25-4.21-16.24-6.63-47.62 9.93-74.73C656.43 22.74 726 0 726 0z'/%3E%3C/svg%3E") no-repeat 50% 50%;
|
||||
-webkit-mask-size: 100%;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
transform: translateY(8px)
|
||||
}
|
||||
|
||||
button:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
box-shadow: 0px 0 0 0 white;
|
||||
transition: all 2s ease;
|
||||
}
|
||||
|
||||
button:hover:after {
|
||||
box-shadow: 0px -13px 56px 12px #ffffffa6;
|
||||
}
|
||||
|
||||
button span {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
font-size: 15px;
|
||||
font-weight: 100;
|
||||
left: 50%;
|
||||
top: 39%;
|
||||
letter-spacing: 3px;
|
||||
text-align: center;
|
||||
transform: translate(-50%,-50%);
|
||||
color: rgb(222, 13, 13);
|
||||
transition: all 2s ease;
|
||||
}
|
||||
|
||||
button:hover span {
|
||||
color: white;
|
||||
}
|
||||
|
||||
button:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 100%;
|
||||
background-color: black;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transition: all 1s ease;
|
||||
}
|
||||
|
||||
button:hover:before {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
8
src/views/TestView2.vue
Normal file
@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<TestView></TestView>
|
||||
<TestViewO></TestViewO>
|
||||
</template>
|
||||
<script>
|
||||
import TestView from '@/components/TestView.vue'
|
||||
import TestViewO from '@/components/TestViewO.vue'
|
||||
</script>
|
@ -1,8 +1,8 @@
|
||||
<!-- eslint-disable vue/multi-word-component-names -->
|
||||
<template>
|
||||
<a-layout>
|
||||
<a-layout style="padding: 1vw">
|
||||
<a-layout-sider width="30vw">
|
||||
<a-layout style="padding: 1vmax">
|
||||
<a-layout-sider width="22vmax">
|
||||
<a-menu
|
||||
id="services_list"
|
||||
class="gpal-menu"
|
||||
|
126
test/Lock.js
Normal file
@ -0,0 +1,126 @@
|
||||
const {
|
||||
time,
|
||||
loadFixture,
|
||||
} = require("@nomicfoundation/hardhat-network-helpers");
|
||||
const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs");
|
||||
const { expect } = require("chai");
|
||||
|
||||
describe("Lock", function () {
|
||||
// We define a fixture to reuse the same setup in every test.
|
||||
// We use loadFixture to run this setup once, snapshot that state,
|
||||
// and reset Hardhat Network to that snapshot in every test.
|
||||
async function deployOneYearLockFixture() {
|
||||
const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60;
|
||||
const ONE_GWEI = 1_000_000_000;
|
||||
|
||||
const lockedAmount = ONE_GWEI;
|
||||
const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS;
|
||||
|
||||
// Contracts are deployed using the first signer/account by default
|
||||
const [owner, otherAccount] = await ethers.getSigners();
|
||||
|
||||
const Lock = await ethers.getContractFactory("Lock");
|
||||
const lock = await Lock.deploy(unlockTime, { value: lockedAmount });
|
||||
|
||||
return { lock, unlockTime, lockedAmount, owner, otherAccount };
|
||||
}
|
||||
|
||||
describe("Deployment", function () {
|
||||
it("Should set the right unlockTime", async function () {
|
||||
const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture);
|
||||
|
||||
expect(await lock.unlockTime()).to.equal(unlockTime);
|
||||
});
|
||||
|
||||
it("Should set the right owner", async function () {
|
||||
const { lock, owner } = await loadFixture(deployOneYearLockFixture);
|
||||
|
||||
expect(await lock.owner()).to.equal(owner.address);
|
||||
});
|
||||
|
||||
it("Should receive and store the funds to lock", async function () {
|
||||
const { lock, lockedAmount } = await loadFixture(
|
||||
deployOneYearLockFixture
|
||||
);
|
||||
|
||||
expect(await ethers.provider.getBalance(lock.address)).to.equal(
|
||||
lockedAmount
|
||||
);
|
||||
});
|
||||
|
||||
it("Should fail if the unlockTime is not in the future", async function () {
|
||||
// We don't use the fixture here because we want a different deployment
|
||||
const latestTime = await time.latest();
|
||||
const Lock = await ethers.getContractFactory("Lock");
|
||||
await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith(
|
||||
"Unlock time should be in the future"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Withdrawals", function () {
|
||||
describe("Validations", function () {
|
||||
it("Should revert with the right error if called too soon", async function () {
|
||||
const { lock } = await loadFixture(deployOneYearLockFixture);
|
||||
|
||||
await expect(lock.withdraw()).to.be.revertedWith(
|
||||
"You can't withdraw yet"
|
||||
);
|
||||
});
|
||||
|
||||
it("Should revert with the right error if called from another account", async function () {
|
||||
const { lock, unlockTime, otherAccount } = await loadFixture(
|
||||
deployOneYearLockFixture
|
||||
);
|
||||
|
||||
// We can increase the time in Hardhat Network
|
||||
await time.increaseTo(unlockTime);
|
||||
|
||||
// We use lock.connect() to send a transaction from another account
|
||||
await expect(lock.connect(otherAccount).withdraw()).to.be.revertedWith(
|
||||
"You aren't the owner"
|
||||
);
|
||||
});
|
||||
|
||||
it("Shouldn't fail if the unlockTime has arrived and the owner calls it", async function () {
|
||||
const { lock, unlockTime } = await loadFixture(
|
||||
deployOneYearLockFixture
|
||||
);
|
||||
|
||||
// Transactions are sent using the first signer by default
|
||||
await time.increaseTo(unlockTime);
|
||||
|
||||
await expect(lock.withdraw()).not.to.be.reverted;
|
||||
});
|
||||
});
|
||||
|
||||
describe("Events", function () {
|
||||
it("Should emit an event on withdrawals", async function () {
|
||||
const { lock, unlockTime, lockedAmount } = await loadFixture(
|
||||
deployOneYearLockFixture
|
||||
);
|
||||
|
||||
await time.increaseTo(unlockTime);
|
||||
|
||||
await expect(lock.withdraw())
|
||||
.to.emit(lock, "Withdrawal")
|
||||
.withArgs(lockedAmount, anyValue); // We accept any value as `when` arg
|
||||
});
|
||||
});
|
||||
|
||||
describe("Transfers", function () {
|
||||
it("Should transfer the funds to the owner", async function () {
|
||||
const { lock, unlockTime, lockedAmount, owner } = await loadFixture(
|
||||
deployOneYearLockFixture
|
||||
);
|
||||
|
||||
await time.increaseTo(unlockTime);
|
||||
|
||||
await expect(lock.withdraw()).to.changeEtherBalances(
|
||||
[owner, lock],
|
||||
[lockedAmount, -lockedAmount]
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|