1404/10/28-base

This commit is contained in:
2026-01-18 13:01:46 +03:30
parent f95b0cef95
commit 9d96ae106b
455 changed files with 58164 additions and 0 deletions
@@ -0,0 +1,104 @@
<template>
<div
:style="findPositionStyle(props.selfIndex)"
class="card relative"
@click="localValue = props.selfIndex"
>
<!-- <img :src="ly1" class="absolute h-full w-full object-cover rounded-2xl" alt="">-->
<!-- <img :src="ly2 " class="absolute h-full w-full object-cover rounded-2xl" alt="">-->
<div class="flex flex-col items-center">
<img :src="img" alt="" class="w-full h-full" />
<div class="mt-[1.5vh] text-white w-full text-center text-xl font-bold" dir="ltr">
{{ useCardNumber(props.cardNumber) }}
</div>
<div class="mt-3 text-white text-lg">{{ useShabaNumber(props.shaba) }}</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { useCardNumber, useShabaNumber } from '@/utils/useCardNumber'
interface Prop {
sliderIndex: number
selfIndex: number
img: string
color?: string
}
const localValue = computed({
get() {
return props.sliderIndex
},
set(value) {
emits('update:sliderIndex', value)
}
})
const props = defineProps<Prop>()
const emits = defineEmits(['update:sliderIndex'])
function findPositionStyle(pos: number) {
// console.log(localValue.value)
// console.log(pos,index)
let debug
if (pos === props.sliderIndex) {
debug = `width: 100%; z-index: 100; opacity: 1;/* margin-top: -160px;*/ top: 20%; position: absolute; background-color: ${props.color};`
} /*if (pos > index.value)*/ else {
// debug = `w-[${100 - Math.abs(index.value-pos) * 2}%] z-${100 - Math.abs(index.value-pos)}`
debug = `width: ${100 - Math.abs(props.sliderIndex - pos) * 3}%;
z-index: ${100 - Math.abs(props.sliderIndex - pos)};
opacity: ${1 - Math.abs((props.sliderIndex - pos) * 15) / 100};
/*
margin-top: ${-160 - Math.abs((props.sliderIndex - pos) * 15)}px;
*/
position: absolute;
top : ${
pos > props.sliderIndex
? checkTopLimit(topDetail(true, pos) as number)
? 100
: 35 +
Math.abs((props.sliderIndex - pos) * (35 - Math.abs((props.sliderIndex - pos) * 4)))
: checkTopLimit(topDetail(false, pos) as number)
? 0
: 35 - Math.abs((props.sliderIndex - pos) * (35 - Math.abs((props.sliderIndex - pos) * 4)))
}%;
background-color: ${props.color};`
}
// console.log(debug)
return debug
}
/**
* /!*checkTopLimit(topDetail(true, pos) as number) ? 100 :*!/ topDetail(true, pos) :
* /!*checkTopLimit(topDetail(false, pos) as number) ? 0 :*!/ topDetail(false, pos)
*/
function topDetail(isAfterIndex: boolean, pos: number) {
if (isAfterIndex)
return 35 + Math.abs((props.sliderIndex - pos) * (35 - Math.abs((props.sliderIndex - pos) * 4)))
else
return (
35 - Math.abs((props.sliderIndex - pos) * (35 - Math.abs((props.sliderIndex - pos) * 4))) < 0
)
}
function checkTopLimit(val: number) {
return val > 100 || val < 0
}
</script>
<style lang="sass" scoped>
.card
height: fit-content
width: 100%
align-self: center
border-radius: 24px
transition: .5s
.card:first-child
margin-top: 0 !important
</style>
+178
View File
@@ -0,0 +1,178 @@
<template>
<div >
<div class="flex">
<div :class="isUp? 'bg-green-50':'bg-red-50'" class="rounded-lg p-4 h-fit w-fit flex justify-center items-center">
<Icon :class="isUp? 'text-green-600':'text-red-600'"
:icon="`vuesax-linear:${isUp? 'tick-circle':'close-circle'}`"/>
</div>
<div class=" w-full mr-2 ">
<div class="flex w-full text-xs ">{{item.note ?? '-'}}</div>
<div class="flex mt-1 text-xs">
<div>وضعیت:</div>
<div :class="'text-green-600'" class="mr-1" v-if="item.transaction[0]">موفق</div>
<div :class="'text-red-600'" class="mr-1" v-else>ناموفق</div>
</div>
<div class="flex mt-1 text-xs ">
<div class="w-4rem">کد پیگیری: </div>
<div class=" mr-1">{{item.tracked_number ?? '-'}}</div>
</div>
</div>
<div class="w-full mr-3">
<div class="flex justify-between w-full">
<div>{{ item.type_str }}</div>
<div>{{ toJalaliNotime(item.created_at) }}</div>
</div>
<div class="flex justify-between mt-2">
<div :class="item.gold >= 0? 'text-green-600':'text-red-600'" class="text-gray-500 text-xs number-ltr">
<!-- {{ item.gold }}
<div>گرم</div>-->
</div>
<div class="text-gray-500 flex gap-1 text-xs items-center">
<div :class="item.cash > 0 ? 'text-green-600':'text-red-600'" class="text-base number-ltr">
{{ usePriceWithoutType(item.cash ?? 0) }}
</div>
ریال
</div>
</div>
</div>
</div>
<div v-if="isGold" class="flex w-full justify-between mt-2">
<div class="text-gray-500">قیمت معامله:</div>
<div class="text-gray-500 flex gap-1 text-xs items-center">
<div class="text-base">{{ usePriceWithoutType((Math.abs(item.cash) / Math.abs(item.gold)).toFixed(0)) }}</div>
ریال
</div>
</div>
<!-- <div class="flex w-full justify-between mt-2">
<div class="text-gray-500">وضعیت :</div>
<div class="text-gray-500 flex gap-1 text-xs items-center">
<ATag class="!py-1 !px-6 !ml-0" color="blue">
{{ item.order?.sts_str ?? '' }}
</ATag>
</div>
</div>-->
<!-- <div v-else class="h-8"></div>-->
<a-divider class="!my-3"/>
<BasicActionSheet v-model:show="infoVisible">
<div class="font-bold text-lg">{{ props.item.type_str }}</div>
<div class="pb-20 mt-5">
<div class="flex justify-between mb-3">
<div class="text-black">مبلغ:</div>
<div :class="item.cash > 0? 'text-green-600' : 'text-red-600'" class="flex text-xs items-center">
<div class="text-base ml-1 number-ltr">{{ usePriceWithoutType(item.cash) }}</div>
ریال
</div>
</div>
<div class="flex justify-between mb-3">
<div class="text-black">مقدار طلا مبادله شده:</div>
<div :class="item.gold >= 0? 'text-green-600' : 'text-red-600'" class="flex text-xs items-center">
<div class="text-base ml-1 number-ltr">{{ item.gold }}</div>
گرم
</div>
</div>
<div v-if="item.order" class="flex justify-between mb-3">
<div class="text-black">قیمت هر گرم طلا حین معامله:</div>
<div class="flex text-xs items-center number-ltr">
<div class="text-base ml-1">{{ usePriceWithoutType(item.order?.price?? 0) }}</div>
ریال
</div>
</div>
<div class="flex justify-between mb-3">
<div class="text-black">موجودی کیف پول:</div>
<div :class="item.cash > 0? 'text-green-600' : 'text-red-600'" class="flex text-xs items-center">
<div class="text-base number-ltr">{{ usePriceWithoutType(item.balance_cash ?? 0) }}</div>
ریال
</div>
</div>
<div class="flex justify-between mb-3">
<div class="text-black">موجودی کیف طلا:</div>
<div class="flex text-xs text-yellow-700 items-center">
<div class="text-base ml-1">{{ item.balance_gold }}</div>
گرم
</div>
</div>
<!-- <div class="flex justify-between mb-3">
<div class="text-black">موجودی کیف پول:</div>
<div class="flex text-xs items-center" :class="isUp? 'text-green-600' : 'text-red-600'"><div class="text-base">{{usePriceWithoutType(12000000)}}</div>ریال</div>
</div>
<div class="flex justify-between mb-3">
<div class="text-black">موجودی کیف طلا:</div>
<div class="flex items-center" :class="isUp? 'text-red-600' : 'text-green-600'">60 گرم</div>
</div>-->
<div class="flex justify-between mb-3">
<div class="text-black">وضعیت:</div>
<div class="flex text-xs items-center">
<ATag :color="item.active? 'blue': 'red'" class="!py-1 !px-6 !ml-0">{{
item.order?.sts_str
}}
</ATag>
</div>
</div>
<div class="flex justify-between mb-3">
<div class="text-black">تاریخ:</div>
<div>{{ toJalaliNotime(item.expire_at) }}</div>
</div>
<div class="flex justify-between mb-3">
<div class="text-black">زمان:</div>
<div>{{ toTime(item.expire_at) }}</div>
</div>
<!-- <div class="flex justify-between mb-3">
<div class="text-black">وضعیت معامله:</div>
<div class="flex text-xs items-center">
<ATag class="!py-1 !px-6 !ml-0" color="orange">
معاملات باز
</ATag>
</div>
</div>-->
<div v-if="item.eaj" class="flex justify-between mb-3">
<div class="text-black">مهلت ارسال فیش:</div>
<div>{{ item.eaj }}</div>
</div>
<BasicButton class="w-full mt-5" @click="infoVisible = false">بازگشت</BasicButton>
</div>
</BasicActionSheet>
</div>
</template>
<script lang="ts" setup>
import Icon from "@/components/BasicPacks/BasicIcon.vue";
import {usePriceWithoutType} from "../../../../utils/usePrice";
import BasicActionSheet from "@/components/BasicPacks/BasicActionSheet.vue";
import {computed, ref} from "vue";
import BasicButton from "@/components/BasicPacks/BasicButton.vue";
import type {Transaction} from "@/models/transaction";
import {toJalaliNotime, toJalaliOutOfUTC, toTime} from "../../../../utils/useDateTime";
const infoVisible = ref<boolean>(false)
interface Prop {
item: Transaction
}
const props = withDefaults(defineProps<Prop>(), {})
// const isUp = computed(() => props.item.type === 3 || props.item.type === 1)
const isUp = computed(() => props.item.transaction[0])
const isGold = computed(() => props.item.type === 1 || props.item.type === 2 || props.item.type === 10)
/*const title = computed(() => {
if (isUp.value) {
if (isGold.value) {
return 'واریز ریالی'
} else {
return 'خرید طلا'
}
} else {
if (isGold.value) {
return 'برداشت ریالی'
} else {
return 'فروش طلا'
}
}
})*/
</script>
<style scoped>
</style>
@@ -0,0 +1,429 @@
<template>
<van-dialog
class="updateButton"
confirm-button-text="متوجه شدم"
:show-confirm-button="false"
@confirm="update()"
>
<div class="flex flex-col items-center p-2 mt-7 mb-3">
<div class="typewriter">
<div class="slide"><i></i></div>
<div class="paper"></div>
<div class="keyboard"></div>
</div>
<div class="font-bold mt-5">در حال انجام تراکنش</div>
<div class="home_appear_fade_in_up mt-2 text-sm mb-5">
سفارش شما در حال پیگیری است، لطفا صبور باشید!
</div>
</div>
</van-dialog>
</template>
<script setup lang="ts">
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import { update } from 'lodash'
import { ref } from 'vue'
interface Prop {
title: string
info?: string
infoHead?: string
isLine?: boolean
value?: string | number
}
const props = withDefaults(defineProps<Prop>(), {
isLine: false
})
</script>
<style scoped lang="less">
/* From Uiverse.io by Nawsome */
.typewriter {
--blue: #5c86ff;
--blue-dark: #275efe;
--key: #fff;
--paper: #eef0fd;
--text: #d3d4ec;
--tool: #fbc56c;
--duration: 3s;
position: relative;
-webkit-animation: bounce05 var(--duration) linear infinite;
animation: bounce05 var(--duration) linear infinite;
}
.typewriter .slide {
width: 92px;
height: 20px;
border-radius: 3px;
margin-left: 14px;
transform: translateX(14px);
background: linear-gradient(var(--blue), var(--blue-dark));
-webkit-animation: slide05 var(--duration) ease infinite;
animation: slide05 var(--duration) ease infinite;
}
.typewriter .slide:before,
.typewriter .slide:after,
.typewriter .slide i:before {
content: '';
position: absolute;
background: var(--tool);
}
.typewriter .slide:before {
width: 2px;
height: 8px;
top: 6px;
left: 100%;
}
.typewriter .slide:after {
left: 94px;
top: 3px;
height: 14px;
width: 6px;
border-radius: 3px;
}
.typewriter .slide i {
display: block;
position: absolute;
right: 100%;
width: 6px;
height: 4px;
top: 4px;
background: var(--tool);
}
.typewriter .slide i:before {
right: 100%;
top: -2px;
width: 4px;
border-radius: 2px;
height: 14px;
}
.typewriter .paper {
position: absolute;
left: 24px;
top: -26px;
width: 40px;
height: 46px;
border-radius: 5px;
background: var(--paper);
transform: translateY(46px);
-webkit-animation: paper05 var(--duration) linear infinite;
animation: paper05 var(--duration) linear infinite;
}
.typewriter .paper:before {
content: '';
position: absolute;
left: 6px;
right: 6px;
top: 7px;
border-radius: 2px;
height: 4px;
transform: scaleY(0.8);
background: var(--text);
box-shadow:
0 12px 0 var(--text),
0 24px 0 var(--text),
0 36px 0 var(--text);
}
.typewriter .keyboard {
width: 120px;
height: 56px;
margin-top: -10px;
z-index: 1;
position: relative;
}
.typewriter .keyboard:before,
.typewriter .keyboard:after {
content: '';
position: absolute;
}
.typewriter .keyboard:before {
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 7px;
background: linear-gradient(135deg, var(--blue), var(--blue-dark));
transform: perspective(10px) rotateX(2deg);
transform-origin: 50% 100%;
}
.typewriter .keyboard:after {
left: 2px;
top: 25px;
width: 11px;
height: 4px;
border-radius: 2px;
box-shadow:
15px 0 0 var(--key),
30px 0 0 var(--key),
45px 0 0 var(--key),
60px 0 0 var(--key),
75px 0 0 var(--key),
90px 0 0 var(--key),
22px 10px 0 var(--key),
37px 10px 0 var(--key),
52px 10px 0 var(--key),
60px 10px 0 var(--key),
68px 10px 0 var(--key),
83px 10px 0 var(--key);
-webkit-animation: keyboard05 var(--duration) linear infinite;
animation: keyboard05 var(--duration) linear infinite;
}
@keyframes bounce05 {
85%,
92%,
100% {
transform: translateY(0);
}
89% {
transform: translateY(-4px);
}
95% {
transform: translateY(2px);
}
}
@keyframes slide05 {
5% {
transform: translateX(14px);
}
15%,
30% {
transform: translateX(6px);
}
40%,
55% {
transform: translateX(0);
}
65%,
70% {
transform: translateX(-4px);
}
80%,
89% {
transform: translateX(-12px);
}
100% {
transform: translateX(14px);
}
}
@keyframes paper05 {
5% {
transform: translateY(46px);
}
20%,
30% {
transform: translateY(34px);
}
40%,
55% {
transform: translateY(22px);
}
65%,
70% {
transform: translateY(10px);
}
80%,
85% {
transform: translateY(0);
}
92%,
100% {
transform: translateY(46px);
}
}
@keyframes keyboard05 {
5%,
12%,
21%,
30%,
39%,
48%,
57%,
66%,
75%,
84% {
box-shadow:
15px 0 0 var(--key),
30px 0 0 var(--key),
45px 0 0 var(--key),
60px 0 0 var(--key),
75px 0 0 var(--key),
90px 0 0 var(--key),
22px 10px 0 var(--key),
37px 10px 0 var(--key),
52px 10px 0 var(--key),
60px 10px 0 var(--key),
68px 10px 0 var(--key),
83px 10px 0 var(--key);
}
9% {
box-shadow:
15px 2px 0 var(--key),
30px 0 0 var(--key),
45px 0 0 var(--key),
60px 0 0 var(--key),
75px 0 0 var(--key),
90px 0 0 var(--key),
22px 10px 0 var(--key),
37px 10px 0 var(--key),
52px 10px 0 var(--key),
60px 10px 0 var(--key),
68px 10px 0 var(--key),
83px 10px 0 var(--key);
}
18% {
box-shadow:
15px 0 0 var(--key),
30px 0 0 var(--key),
45px 0 0 var(--key),
60px 2px 0 var(--key),
75px 0 0 var(--key),
90px 0 0 var(--key),
22px 10px 0 var(--key),
37px 10px 0 var(--key),
52px 10px 0 var(--key),
60px 10px 0 var(--key),
68px 10px 0 var(--key),
83px 10px 0 var(--key);
}
27% {
box-shadow:
15px 0 0 var(--key),
30px 0 0 var(--key),
45px 0 0 var(--key),
60px 0 0 var(--key),
75px 0 0 var(--key),
90px 0 0 var(--key),
22px 12px 0 var(--key),
37px 10px 0 var(--key),
52px 10px 0 var(--key),
60px 10px 0 var(--key),
68px 10px 0 var(--key),
83px 10px 0 var(--key);
}
36% {
box-shadow:
15px 0 0 var(--key),
30px 0 0 var(--key),
45px 0 0 var(--key),
60px 0 0 var(--key),
75px 0 0 var(--key),
90px 0 0 var(--key),
22px 10px 0 var(--key),
37px 10px 0 var(--key),
52px 12px 0 var(--key),
60px 12px 0 var(--key),
68px 12px 0 var(--key),
83px 10px 0 var(--key);
}
45% {
box-shadow:
15px 0 0 var(--key),
30px 0 0 var(--key),
45px 0 0 var(--key),
60px 0 0 var(--key),
75px 0 0 var(--key),
90px 2px 0 var(--key),
22px 10px 0 var(--key),
37px 10px 0 var(--key),
52px 10px 0 var(--key),
60px 10px 0 var(--key),
68px 10px 0 var(--key),
83px 10px 0 var(--key);
}
54% {
box-shadow:
15px 0 0 var(--key),
30px 2px 0 var(--key),
45px 0 0 var(--key),
60px 0 0 var(--key),
75px 0 0 var(--key),
90px 0 0 var(--key),
22px 10px 0 var(--key),
37px 10px 0 var(--key),
52px 10px 0 var(--key),
60px 10px 0 var(--key),
68px 10px 0 var(--key),
83px 10px 0 var(--key);
}
63% {
box-shadow:
15px 0 0 var(--key),
30px 0 0 var(--key),
45px 0 0 var(--key),
60px 0 0 var(--key),
75px 0 0 var(--key),
90px 0 0 var(--key),
22px 10px 0 var(--key),
37px 10px 0 var(--key),
52px 10px 0 var(--key),
60px 10px 0 var(--key),
68px 10px 0 var(--key),
83px 12px 0 var(--key);
}
72% {
box-shadow:
15px 0 0 var(--key),
30px 0 0 var(--key),
45px 2px 0 var(--key),
60px 0 0 var(--key),
75px 0 0 var(--key),
90px 0 0 var(--key),
22px 10px 0 var(--key),
37px 10px 0 var(--key),
52px 10px 0 var(--key),
60px 10px 0 var(--key),
68px 10px 0 var(--key),
83px 10px 0 var(--key);
}
81% {
box-shadow:
15px 0 0 var(--key),
30px 0 0 var(--key),
45px 0 0 var(--key),
60px 0 0 var(--key),
75px 0 0 var(--key),
90px 0 0 var(--key),
22px 10px 0 var(--key),
37px 12px 0 var(--key),
52px 10px 0 var(--key),
60px 10px 0 var(--key),
68px 10px 0 var(--key),
83px 10px 0 var(--key);
}
}
</style>
@@ -0,0 +1,158 @@
<template>
<div
:style="findPositionStyle(props.selfIndex)"
class="card relative"
@click="localValue = props.selfIndex"
>
<div class="p-3 flex flex-col items-center">
<div class="flex justify-between w-full">
<div class="text-white font-bold text-lg w-full">{{ props.title }}</div>
<div
class="text-white px-2 flex justify-center items-center rounded-lg w-5rem"
:class="active ? 'bg-green-600' : 'bg-red-600'"
>
{{ active ? 'فعال' : 'غیر فعال' }}
</div>
</div>
<div
v-if="props.cardNumber"
class="mt-[1.5vh] text-white w-full text-center text-xl font-bold"
dir="ltr"
>
{{ useCardNumber(props.cardNumber) }}
</div>
<div v-if="props.shaba" class="mt-3 text-white text-lg">
{{ useShabaNumber(props.shaba) }}
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { useCardNumber, useShabaNumber } from '@/utils/useCardNumber'
interface Prop {
sliderIndex: number
selfIndex: number
title?: string
cardNumber?: string
shaba?: string
color?: string
active?: boolean
}
const localValue = computed({
get() {
return props.sliderIndex
},
set(value) {
emits('update:sliderIndex', value)
}
})
const props = defineProps<Prop>()
const emits = defineEmits(['update:sliderIndex'])
function findPositionStyle(pos: number) {
// console.log(localValue.value)
// console.log(pos,index)
let debug
if (pos === props.sliderIndex) {
debug = `width: 100%; z-index: 100; opacity: 1;/* margin-top: -160px;*/ top: 20%; position: absolute; background-color: ${props.color};`
} /*if (pos > index.value)*/ else {
// debug = `w-[${100 - Math.abs(index.value-pos) * 2}%] z-${100 - Math.abs(index.value-pos)}`
debug = `width: ${100 - Math.abs(props.sliderIndex - pos) * 10}%;
z-index: ${100 - Math.abs(props.sliderIndex - pos)};
position: absolute;
top : ${
pos > props.sliderIndex
? checkTopLimit(topDetail(true, pos) as number)
? 100
: 20 +
Math.abs((props.sliderIndex - pos) * (18 - Math.abs((props.sliderIndex - pos) * 4)))
: checkTopLimit(topDetail(false, pos) as number)
? 0
: 20 - Math.abs((props.sliderIndex - pos) * (18 - Math.abs((props.sliderIndex - pos) * 4)))
}%;
background-color: ${props.color};`
}
console.log(debug, topDetail(true, pos))
return debug
}
/*
function findPositionStyle(pos: number) {
// console.log(localValue.value)
// console.log(pos,index)
let debug
if (pos === props.sliderIndex) {
debug = `width: 100%; z-index: 100; opacity: 1;/!* margin-top: -160px;*!/ top: 20%; position: absolute; background-color: ${props.color};`
} else /!*if (pos > index.value)*!/{
// debug = `w-[${100 - Math.abs(index.value-pos) * 2}%] z-${100 - Math.abs(index.value-pos)}`
debug = `width: ${100 - Math.abs(props.sliderIndex - pos) * 10}%;
z-index: ${100 - Math.abs(props.sliderIndex - pos)};
/!*
opacity: ${1 - Math.abs((props.sliderIndex - pos) * 15) / 100};
*!/
/!*
margin-top: ${-160 - Math.abs((props.sliderIndex - pos) * 15)}px;
*!/
position: absolute;
top : ${pos > props.sliderIndex ?
checkTopLimit(topDetail(true, pos) as number) ? 100 :
(20 + Math.abs((props.sliderIndex - pos) * (18 - (Math.abs((props.sliderIndex - pos) * 4))))) :
checkTopLimit(topDetail(false, pos) as number) ? 0 :
(20 - Math.abs((props.sliderIndex - pos) * (18 - (Math.abs((props.sliderIndex - pos) * 4)))))}%;
background-color: ${props.color};`
}
console.log(debug)
return debug
}
*/
/**
* /!*checkTopLimit(topDetail(true, pos) as number) ? 100 :*!/ topDetail(true, pos) :
* /!*checkTopLimit(topDetail(false, pos) as number) ? 0 :*!/ topDetail(false, pos)
*/
function topDetail(isAfterIndex: boolean, pos: number) {
/* console.log((20 - Math.abs((props.sliderIndex - pos) * (24 - (Math.abs((props.sliderIndex - pos) * 4))))), pos)
console.log(Math.abs((props.sliderIndex - pos)) * (24 - (Math.abs((props.sliderIndex - pos) * 4))))*/
console.log(
20 - Math.abs((props.sliderIndex - pos) * (24 - Math.abs((props.sliderIndex - pos) * 4)))
)
/* if (isAfterIndex) console.log(20 + Math.abs(props.sliderIndex - pos))
else console.log(20 - Math.abs(props.sliderIndex - pos))*/
if (isAfterIndex)
return 20 + Math.abs((props.sliderIndex - pos) * (18 - Math.abs((props.sliderIndex - pos) * 4)))
else
return 20 - Math.abs((props.sliderIndex - pos) * (18 - Math.abs((props.sliderIndex - pos) * 4)))
}
/*
function topDetail(isAfterIndex: boolean, pos: number) {
console.log(pos, isAfterIndex, (20 + Math.abs((props.sliderIndex - pos) * (24 - (Math.abs((props.sliderIndex - pos) * 4))))))
if (isAfterIndex) return (20 + Math.abs((props.sliderIndex - pos) * (24 - (Math.abs((props.sliderIndex - pos) * 4)))))
else return (20 - Math.abs((props.sliderIndex - pos) * (24 - (Math.abs((props.sliderIndex - pos) * 4))))) < 0 //12*64
}
*/
function checkTopLimit(val: number) {
return val > 100 || val < 0
}
</script>
<style lang="sass" scoped>
.card
height: 22vh
width: 100%
align-self: center
border-radius: 24px
transition: .5s
.card:first-child
margin-top: 0 !important
</style>
@@ -0,0 +1,162 @@
<template lang="pug">
.container
.slider
.slide(data-slide='1' style="background-color: green")
.slide(data-slide='2' style="background-color: red")
.slide(data-slide='3' style="background-color: orange")
.slide.slide--active(data-slide='4' style="background-color: blue")
.slide(data-slide='5' style="background-color: violet")
.slide(data-slide='5' style="background-color: primary")
.slide(data-slide='5' style="background-color: pink")
.slide(data-slide='5' style="background-color: teal")
.controls
#back Back
#forvard Forvard
</template>
<script setup>
document.addEventListener('DOMContentLoaded', function () {
renderSlider('.slider');
});
const nextSlide = () => {
let activeSlide = document.querySelector('.slide--active');
let nextSlide = activeSlide.nextElementSibling;
if (nextSlide) {
activeSlide.classList.remove('slide--active');
nextSlide.classList.remove('next');
nextSlide.classList.add('slide--active');
renderSlides();
renderBtns();
}
}
const renderBtns = () => {
let nextBtn = document.querySelector('#forvard');
let prevBtn = document.querySelector('#back');
let activeSlide = document.querySelector('.slide--active');
let prevSlide = activeSlide.previousElementSibling;
!prevSlide ? prevBtn.classList.add('disabled')
: prevBtn.classList.remove('disabled');
let nextSlide = activeSlide.nextElementSibling;
!nextSlide ? nextBtn.classList.add('disabled')
: nextBtn.classList.remove('disabled');
}
const prevSlide = () => {
let activeSlide = document.querySelector('.slide--active');
let prevSlide = activeSlide.previousElementSibling;
if (prevSlide) {
activeSlide.classList.remove('slide--active');
prevSlide.classList.remove('prev');
prevSlide.classList.add('slide--active');
renderSlides();
renderBtns();
}
}
const renderSlides = () => {
let slides = document.querySelectorAll('.slide');
if (!slides) {
return;
}
let activeSlide = document.querySelector('.slide--active');
if (!activeSlide) {
activeSlide = slides.item(0);
activeSlide.classList.add('slide--active');
}
[].forEach.call(slides, function (slide) {
slide.classList.remove('prev', 'next')
});
let prevSlide = activeSlide.previousElementSibling;
prevSlide && prevSlide.classList.add('prev');
let nextSlide = activeSlide.nextElementSibling;
nextSlide && nextSlide.classList.add('next');
}
const renderSlider = (element) => {
const slider = document.querySelector(element);
if (slider) {
let nextButton = document.querySelector("#forvard");
nextButton.addEventListener('click', function () {
nextSlide();
})
let prevButton = document.querySelector("#back");
prevButton.addEventListener('click', function () {
prevSlide();
})
renderSlides();
}
}
</script>
<style lang="sass" scoped>
.container
display: flex
flex-flow: column
justify-content: center
margin: 50px auto 0
width: 500px
height: 300px
.controls
display: flex
justify-content: center
div
padding: 12px 14px
cursor: pointer
border: 1px solid #fff
color: #fff
font-size: 16px
font-weight: bold
margin: 0 5px
border-radius: 10px
&.disabled
opacity: 0
cursor: default
.slider
position: relative
width: 100%
height: 100%
.slide
position: absolute
top: 25%
left: 10%
width: 80%
height: 50%
background-color: red
border: 1px solid #fff
border-radius: 15px
opacity: 0
transition: all 0.7s ease-out
&--active
opacity: 1
z-index: 9
.prev,
.next
opacity: .3
.prev
transform: translate(0, -30%) scale(0.8)
.next
transform: translate(0, 30%) scale(0.8)
</style>
@@ -0,0 +1,259 @@
<template>
<div ref="container" class=" h-[38vh] flex items-center">
<div ref="el" class="w-full flex flex-col relative h-full test">
<CardItem v-for="(item,i) in props?.items" :key="i" v-model:sliderIndex="index" :card-number="item?.cart_number"
:color="colors[i%3]"
:self-index="i" :shaba="item?.shaba_number" :title="item?.bank_name" :active="item.sts === 2"/>
<div class="absolute bottom-15vh right-0 left-0 z-100 flex justify-center items-center opacity-70">
<div class="flex gap-1 bg-gray-500 px-2 py-1 rounded-lg">
<Transition name="slide-up" mode="out-in" v-for="i in items.length" :key="i">
<div v-if="i - 1 === index" class="w-2 h-2 rounded-full bg-primary"/>
<div v-else class="w-2 h-2 rounded-full bg-white"/>
</Transition>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, onMounted, ref, watch } from 'vue'
// import {usePointerSwipe} from '@vueuse/core'
// import type {UseSwipeDirection} from '@vueuse/core'
// import type { UseSwipeDirection } from '@vueuse/core'
import { useSwipe } from '@vueuse/core'
import CardItem from './CardItem.vue'
import type { Card } from '@/models/wallet'
const el = ref(null)
const container = ref<HTMLElement | null>(null)
interface Prop {
items: Array<Card>
id: number | string
}
const props = defineProps<Prop>()
const emits = defineEmits(['update:id'])
const localValue = computed({
get() {
return props.id
},
set(value) {
emits('update:id', value)
}
})
// const decideSwip = ref<boolean>(false)
const { direction, isSwiping, lengthX, lengthY } = useSwipe(el/*, {
onSwipeStart(){
console.log('salam')
},
onSwipe(e: PointerEvent, direction: UseSwipeDirection) {
console.log('container',direction)
if (!decideSwip.value){
if (direction === 'up') {
index.value++
} else if (direction === 'down') {
index.value--
}
decideSwip.value = true
}
},
onSwipeEnd(e: PointerEvent){
console.log('container1')
decideSwip.value = false
}
}*/)
function getRandomColor() {
var letters = '0123456789ABCDEF'
var color = '#'
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)]
}
return color
}
const colors = ['#4B84EB', '#889BCD', '#C9A68D']
watch(isSwiping, () => {
// console.log(direction.value)
if (isSwiping.value) {
// console.log('salam')
if (direction.value === 'up' && props.items.length - 1 > index.value) {
index.value++
} else if (direction.value === 'down' && index.value > 0) {
index.value--
}
// console.log(index.value)
}
})
const index = ref<number>(props.items.length - 1)
onMounted(()=> localValue.value = props.items[index.value]?.id)
watch(index, (n: number)=> {
console.log(n)
localValue.value = props.items[n]?.id
})
/*
const items = [
{
title: 'بانک ملی',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک ملی',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک ملت',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک سامان',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک پاسارگاد',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک صادرات',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک ملی',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک ملت',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک سامان',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک پاسارگاد',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
]
*/
// const indexCss = computed(()=> index.value)
// watch(index,()=>{
// key++
// console.log(key)
// })
// let key = 0
/*function findPosition(pos: number) {
// console.log(pos,index)
let debug
if (pos === index.value){
debug = 'w-full z-100'
}
else /!*if (pos > index.value)*!/{
debug = `w-[${100 - Math.abs(index.value-pos) * 2}%] z-${100 - Math.abs(index.value-pos)}`
}
console.log(debug)
return debug
}*/
/*
function mouseUp() {
index.value--
}
function mouseDown() {
console.log('salam')
index.value++
}
*/
/*function findPositionStyle(pos: number) {
// console.log(pos,index)
let debug
if (pos === index.value) {
debug = 'width: 100; z-index: 100; opacity: 1; margin-top: -200px;'
} else /!*if (pos > index.value)*!/{
// debug = `w-[${100 - Math.abs(index.value-pos) * 2}%] z-${100 - Math.abs(index.value-pos)}`
debug = `width: ${100 - Math.abs(index.value - pos) * 3}%;
z-index: ${100 - Math.abs(index.value - pos)};
opacity: ${1 - Math.abs((index.value - pos) * 15) / 100};
margin-top: ${-200 - Math.abs((index.value - pos) * 4)}px;`
}
// console.log(debug)
return debug
}*/
</script>
<style lang="less" scoped>
.slide-up-enter-active,
.slide-up-leave-active {
transition: all 0.25s ease-out;
}
.slide-up-enter-from {
opacity: 0;
transform: translateY(3px);
}
.slide-up-leave-to {
opacity: 0;
transform: translateY(-3px);
}
//.test .card:first-child
// margin-top: 0 !important
//.card
// height: 215px
// width: 100%
// align-self: center
// border-radius: 24px
// transition: .5s
//
//.card:first-child
// margin-top: 0 !important
//$total-items: 30
//@for $i from 1 through $total-items
// .card:nth-child(#{$i})
// @if($i > v-bind(indexCss))
// width: calc(percentage(100 - ($i * 4)) / 100)
// @if($i == v-bind(indexCss))
// width: 100%
// @if($i < v-bind(indexCss))
// width: calc(percentage(100 - ($i * 4)) / 100)
//.animate > div:nth-child(#{$i})
// animation-delay: .08s * $i
</style>
@@ -0,0 +1,262 @@
<template>
<div ref="container" class=" h-[25vh] flex items-center">
<div ref="el" class="w-full flex flex-col relative h-full test">
<!-- <div class="card bg-primary" :style="findPositionStyle(1)" @click="index = 1"></div>
<div class="card bg-red" :style="findPositionStyle(2)" @click="index = 2"></div>
<div class="card bg-yellow" :style="findPositionStyle(3)" @click="index = 3"></div>
<div class="card bg-pink relative" :style="findPositionStyle(4)" @click="index = 4">
<img :src="ly1" class="absolute h-full" alt="">
<img :src="ly2" class="absolute h-full" alt="">
</div>-->
<!-- <CardItem v-model:sliderIndex="index" color="primary" :self-index="1"/>
<CardItem v-model:sliderIndex="index" color="yellow" :self-index="2"/>
<CardItem v-model:sliderIndex="index" color="pink" :self-index="3"/>-->
<!-- <div class="card bg-pink" :style="findPositionStyle(5)" @click="index = 5"></div>
<div class="card bg-pink" :style="findPositionStyle(6)" @click="index = 6"></div>
<div class="card bg-pink" :style="findPositionStyle(7)" @click="index = 7"></div>
<div class="card bg-pink" :style="findPositionStyle(8)" @click="index = 8"></div>
<div class="card bg-pink" :style="findPositionStyle(9)" @click="index = 9"></div>-->
<CardItem v-for="(item,i) in props?.items" :key="i" v-model:sliderIndex="index"
:color="colors[i%3]"
:self-index="i" :img="item"/>
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref, watch } from 'vue'
// import {usePointerSwipe} from '@vueuse/core'
// import type {UseSwipeDirection} from '@vueuse/core'
// import type { UseSwipeDirection } from '@vueuse/core'
import { useSwipe } from '@vueuse/core'
import CardItem from '@/views/base/wallet/components/CardItem.vue'
import type { Card } from '@/models/wallet'
const el = ref(null)
const container = ref<HTMLElement | null>(null)
interface Prop {
items: string[]
}
const props = defineProps<Prop>()
// const decideSwip = ref<boolean>(false)
const { direction, isSwiping, lengthX, lengthY } = useSwipe(el/*, {
onSwipeStart(){
console.log('salam')
},
onSwipe(e: PointerEvent, direction: UseSwipeDirection) {
console.log('container',direction)
if (!decideSwip.value){
if (direction === 'up') {
index.value++
} else if (direction === 'down') {
index.value--
}
decideSwip.value = true
}
},
onSwipeEnd(e: PointerEvent){
console.log('container1')
decideSwip.value = false
}
}*/)
function getRandomColor() {
var letters = '0123456789ABCDEF'
var color = '#'
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)]
}
return color
}
const colors = ['#4B84EB', '#889BCD', '#C9A68D']
// Automatic slider logic
let interval: ReturnType<typeof setInterval>
const intervalTime = 10000 // Time interval for sliding (in milliseconds)
const startAutoSlide = () => {
interval = setInterval(() => {
if (index.value < props.items.length - 1) {
index.value++
} else {
index.value = 0 // Reset to first card when reaching the end
}
}, intervalTime)
}
const stopAutoSlide = () => {
clearInterval(interval)
}
onMounted(() => {
startAutoSlide() // Start sliding when component mounts
})
onUnmounted(() => {
stopAutoSlide() // Clear interval when component is destroyed
})
watch(isSwiping, () => {
// console.log(direction.value)
if (isSwiping.value) {
// console.log('salam')
if (direction.value === 'up' && props.items.length - 1 > index.value) {
index.value++
} else if (direction.value === 'down' && index.value > 0) {
index.value--
}
// console.log(index.value)
}
})
const index = ref<number>(0)
/*
const items = [
{
title: 'بانک ملی',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک ملی',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک ملت',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک سامان',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک پاسارگاد',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک صادرات',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک ملی',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک ملت',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک سامان',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
{
title: 'بانک پاسارگاد',
cardNumber: 6219861918606103,
shaba: 'IR590560611828005106225701',
color: getRandomColor()
},
]
*/
// const indexCss = computed(()=> index.value)
// watch(index,()=>{
// key++
// console.log(key)
// })
// let key = 0
/*function findPosition(pos: number) {
// console.log(pos,index)
let debug
if (pos === index.value){
debug = 'w-full z-100'
}
else /!*if (pos > index.value)*!/{
debug = `w-[${100 - Math.abs(index.value-pos) * 2}%] z-${100 - Math.abs(index.value-pos)}`
}
console.log(debug)
return debug
}*/
/*
function mouseUp() {
index.value--
}
function mouseDown() {
console.log('salam')
index.value++
}
*/
/*function findPositionStyle(pos: number) {
// console.log(pos,index)
let debug
if (pos === index.value) {
debug = 'width: 100; z-index: 100; opacity: 1; margin-top: -200px;'
} else /!*if (pos > index.value)*!/{
// debug = `w-[${100 - Math.abs(index.value-pos) * 2}%] z-${100 - Math.abs(index.value-pos)}`
debug = `width: ${100 - Math.abs(index.value - pos) * 3}%;
z-index: ${100 - Math.abs(index.value - pos)};
opacity: ${1 - Math.abs((index.value - pos) * 15) / 100};
margin-top: ${-200 - Math.abs((index.value - pos) * 4)}px;`
}
// console.log(debug)
return debug
}*/
</script>
<style lang="sass" scoped>
//.test .card:first-child
// margin-top: 0 !important
//.card
// height: 215px
// width: 100%
// align-self: center
// border-radius: 24px
// transition: .5s
//
//.card:first-child
// margin-top: 0 !important
//$total-items: 30
//@for $i from 1 through $total-items
// .card:nth-child(#{$i})
// @if($i > v-bind(indexCss))
// width: calc(percentage(100 - ($i * 4)) / 100)
// @if($i == v-bind(indexCss))
// width: 100%
// @if($i < v-bind(indexCss))
// width: calc(percentage(100 - ($i * 4)) / 100)
//.animate > div:nth-child(#{$i})
// animation-delay: .08s * $i
</style>
@@ -0,0 +1,162 @@
<template lang="pug">
.container
.slider
.slide(data-slide='1' style="background-color: green")
.slide(data-slide='2' style="background-color: red")
.slide(data-slide='3' style="background-color: orange")
.slide.slide--active(data-slide='4' style="background-color: blue")
.slide(data-slide='5' style="background-color: violet")
.slide(data-slide='5' style="background-color: primary")
.slide(data-slide='5' style="background-color: pink")
.slide(data-slide='5' style="background-color: teal")
.controls
#back Back
#forvard Forvard
</template>
<script setup>
document.addEventListener('DOMContentLoaded', function () {
renderSlider('.slider');
});
const nextSlide = () => {
let activeSlide = document.querySelector('.slide--active');
let nextSlide = activeSlide.nextElementSibling;
if (nextSlide) {
activeSlide.classList.remove('slide--active');
nextSlide.classList.remove('next');
nextSlide.classList.add('slide--active');
renderSlides();
renderBtns();
}
}
const renderBtns = () => {
let nextBtn = document.querySelector('#forvard');
let prevBtn = document.querySelector('#back');
let activeSlide = document.querySelector('.slide--active');
let prevSlide = activeSlide.previousElementSibling;
!prevSlide ? prevBtn.classList.add('disabled')
: prevBtn.classList.remove('disabled');
let nextSlide = activeSlide.nextElementSibling;
!nextSlide ? nextBtn.classList.add('disabled')
: nextBtn.classList.remove('disabled');
}
const prevSlide = () => {
let activeSlide = document.querySelector('.slide--active');
let prevSlide = activeSlide.previousElementSibling;
if (prevSlide) {
activeSlide.classList.remove('slide--active');
prevSlide.classList.remove('prev');
prevSlide.classList.add('slide--active');
renderSlides();
renderBtns();
}
}
const renderSlides = () => {
let slides = document.querySelectorAll('.slide');
if (!slides) {
return;
}
let activeSlide = document.querySelector('.slide--active');
if (!activeSlide) {
activeSlide = slides.item(0);
activeSlide.classList.add('slide--active');
}
[].forEach.call(slides, function (slide) {
slide.classList.remove('prev', 'next')
});
let prevSlide = activeSlide.previousElementSibling;
prevSlide && prevSlide.classList.add('prev');
let nextSlide = activeSlide.nextElementSibling;
nextSlide && nextSlide.classList.add('next');
}
const renderSlider = (element) => {
const slider = document.querySelector(element);
if (slider) {
let nextButton = document.querySelector("#forvard");
nextButton.addEventListener('click', function () {
nextSlide();
})
let prevButton = document.querySelector("#back");
prevButton.addEventListener('click', function () {
prevSlide();
})
renderSlides();
}
}
</script>
<style lang="sass" scoped>
.container
display: flex
flex-flow: column
justify-content: center
margin: 50px auto 0
width: 500px
height: 300px
.controls
display: flex
justify-content: center
div
padding: 12px 14px
cursor: pointer
border: 1px solid #fff
color: #fff
font-size: 16px
font-weight: bold
margin: 0 5px
border-radius: 10px
&.disabled
opacity: 0
cursor: default
.slider
position: relative
width: 100%
height: 100%
.slide
position: absolute
top: 25%
left: 10%
width: 80%
height: 50%
background-color: red
border: 1px solid #fff
border-radius: 15px
opacity: 0
transition: all 0.7s ease-out
&--active
opacity: 1
z-index: 9
.prev,
.next
opacity: .3
.prev
transform: translate(0, -30%) scale(0.8)
.next
transform: translate(0, 30%) scale(0.8)
</style>