refactor(ui): replace modal dialogs with toast/sheet components

Remove DialogVant/NotifyVant and add Toast and Sheet components with
useToast, useReveal, and usePageTransition composables. Rework
Navigation, RegisterView, and styles across both apps; rebuild dist assets.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
s.esmaeili
2026-10-04 13:57:25 +03:30
co-authored by Claude Sonnet 5
parent 148b99c4a6
commit c05352d6fd
205 changed files with 3362 additions and 1701 deletions
+1 -1
View File
@@ -44,7 +44,7 @@ withDefaults(
display: none !important;
}
.van-dialog__confirm .van-button__text {
color: #1c2d56;
color: #23493c;
font-weight: 600;
font-size: 15px;
}
@@ -44,7 +44,7 @@ withDefaults(
display: none !important;
}
.van-dialog__confirm .van-button__text {
color: #1c2d56;
color: #23493c;
font-weight: 600;
font-size: 15px;
}
@@ -1,50 +0,0 @@
<!-- Ported from legacy henza_pwa/src/components/NotifyVant.vue -->
<template>
<div v-if="modelValue" class="flex">
<van-notify v-model:show="show" :style="color">
<div class="w-full text-white my-2">
<div class="w-full flex content-end">
<Icon icon="vuesax-linear:info-circle" class="ml-[20px] text-white" size="25" />
<div>
<slot>{{ text }}</slot>
</div>
</div>
</div>
</van-notify>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { Notify as VanNotify } from 'vant'
import Icon from './icon/Icon.vue'
const show = ref(true)
const props = withDefaults(
defineProps<{
modelValue: boolean
timeOut: number
text?: string
color?: string
}>(),
{},
)
const emit = defineEmits<{ (e: 'update:modelValue', value: boolean): void }>()
watch(
() => props.modelValue,
() => {
if (props.timeOut !== -1) showNotify()
},
)
const showNotify = () => {
setTimeout(() => {
emit('update:modelValue', false)
}, props.timeOut)
}
</script>
<!--
Legacy also had a `.notify-enter-active`/`.notify-leave-active` style block
referencing an undefined `notify-in` @keyframes and unused by any
<transition name="notify"> in this component — genuinely dead, dropped.
-->
@@ -78,7 +78,7 @@ const fiat = computed(() => (props.customer ? props.customer.fiatDebtRial.split(
.acct {
border-radius: 20px;
padding: 18px;
background: @ink;
background: @primary;
color: #fff;
box-shadow: 0 22px 44px -32px rgba(20, 22, 26, 0.9);
}
@@ -61,8 +61,8 @@ const emit = defineEmits<{ (e: 'select', cat: HomeCategory): void }>()
}
.rail__chip.is-active {
background: @ink;
border-color: @ink;
background: @primary;
border-color: @primary;
color: #fff;
}
@@ -39,7 +39,7 @@ const perGram = computed(() => (props.quote ? props.quote.pricePerGramRial.split
gap: 10px;
padding: 10px 14px;
border-radius: 14px;
background: @ink;
background: @primary;
color: #fff;
box-shadow: 0 10px 24px -18px rgba(20, 22, 26, 0.9);
}
+3 -3
View File
@@ -1017,11 +1017,11 @@
"vuesax-linear:youtube": "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M17 20H7C4 20 2 18 2 15V9C2 6 4 4 7 4H17C20 4 22 6 22 9V15C22 18 20 20 17 20Z\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M11.4001 9.5L13.9001 11C14.8001 11.6 14.8001 12.5 13.9001 13.1L11.4001 14.6C10.4001 15.2 9.6001 14.7 9.6001 13.6V10.6C9.6001 9.3 10.4001 8.9 11.4001 9.5Z\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>\n",
"vuesax-linear:zel-(zel)": "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M10.5 11.5V14.3L8 15.8L5.5 14.3V11.5L8 10L9.2 10.7L10.5 11.5Z\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\" stroke-linejoin=\"round\"/>\n<path d=\"M18.5 11.5V14.3L16 15.8L13.5 14.3V11.5L14.8 10.7L16 10L18.5 11.5Z\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\" stroke-linejoin=\"round\"/>\n<path d=\"M14.8 9.29999V10.7L13.5 11.5V13.2L12 14.1L10.5 13.2V11.5L9.19995 10.7V9.29999L12 7.79999L14.8 9.29999Z\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\" stroke-linejoin=\"round\"/>\n<path d=\"M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\" stroke-linejoin=\"round\"/>\n</svg>\n",
"vuesax-linear:zoom": "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M6 9.69999V12.5C6 14 7.3 15.3 8.8 15.3H12.5C13 15.3 13.4 14.9 13.4 14.4V11.6C13.4 10.1 12.2 8.79999 10.6 8.79999H6.9C6.4 8.79999 6 9.19999 6 9.69999Z\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\"/>\n<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M18 9.20001V14.8L15.2 12.9V11.1L18 9.20001Z\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\"/>\n</svg>\n",
"vuesax-linear:number-18": "<svg width=\"17\" height=\"14\" viewBox=\"0 0 17 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M1.05502 13.4129C1.05502 13.3105 1.05502 13.1901 1.05502 13.0516C1.05502 12.9131 1.05502 12.7686 1.05502 12.6181C1.05502 12.4675 1.05502 12.32 1.05502 12.1755C1.06084 12.031 1.06665 11.8985 1.07246 11.7781V11.7871C1.07827 11.4981 1.08118 11.2 1.08118 10.8929C1.08699 10.5798 1.0899 10.2516 1.0899 9.90839C1.0899 9.24602 1.08118 8.55957 1.06374 7.84903C1.05212 7.1385 1.01143 6.40086 0.941674 5.63613C0.87192 4.86538 0.764383 4.07054 0.619063 3.25161C0.473743 2.42667 0.267389 1.57161 0 0.686452L2.03157 0C2.32803 0.981505 2.55763 1.92387 2.72039 2.8271C2.88896 3.7243 3.01103 4.58538 3.0866 5.41032C3.16798 6.22925 3.21738 7.01505 3.23482 7.76774C3.25226 8.52043 3.26098 9.24301 3.26098 9.93548C3.26098 10.2787 3.25807 10.6099 3.25226 10.929C3.25226 11.2422 3.24935 11.5432 3.24354 11.8323C3.23773 11.9527 3.23192 12.0852 3.2261 12.2297C3.2261 12.3682 3.2261 12.5097 3.2261 12.6542C3.2261 12.7987 3.2261 12.9372 3.2261 13.0697C3.2261 13.2022 3.2261 13.3166 3.2261 13.4129H1.05502Z\" fill=\"#1C2D56\"/>\n<path d=\"M13.6693 6.05161C14.1052 7.3643 14.608 8.57763 15.1777 9.69161C15.7532 10.7996 16.3606 11.754 17 12.5548L15.3172 14C14.9684 13.5604 14.6226 13.0486 14.2796 12.4645C13.9425 11.8804 13.6082 11.2331 13.2769 10.5226C12.9456 9.80602 12.6201 9.03226 12.3004 8.20129C11.9806 7.37032 11.6639 6.48817 11.35 5.55484C11.1058 6.30753 10.8355 7.08129 10.5391 7.87613C10.2426 8.67097 9.92292 9.44473 9.57996 10.1974C9.24282 10.9441 8.89115 11.6456 8.52494 12.3019C8.15873 12.9523 7.78381 13.5123 7.40016 13.9819L5.69992 12.5548C6.008 12.1815 6.31317 11.748 6.61544 11.2542C6.9177 10.7604 7.21125 10.2335 7.49608 9.67355C7.7809 9.10753 8.0512 8.51742 8.30696 7.90323C8.56854 7.28903 8.80977 6.67183 9.03065 6.05161C9.19341 5.52774 9.35036 5.00086 9.50149 4.47097C9.65262 3.94108 9.78341 3.42925 9.89386 2.93548C10.0043 2.44172 10.0915 1.97806 10.1554 1.54452C10.2252 1.10495 10.2601 0.713549 10.2601 0.370324H12.4224C12.4224 0.737635 12.4515 1.13505 12.5096 1.56258C12.5736 1.99011 12.6578 2.44473 12.7625 2.92645C12.8729 3.40817 13.0037 3.91097 13.1548 4.43484C13.3118 4.95871 13.4833 5.49763 13.6693 6.05161Z\" fill=\"#1C2D56\"/>\n</svg>\n",
"vuesax-linear:number-24": "<svg width=\"21\" height=\"12\" viewBox=\"0 0 21 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M7.59689 0.399477C7.61323 0.446474 7.64862 0.558746 7.70308 0.736292C7.75754 0.913838 7.812 1.12794 7.86646 1.37859C7.92092 1.62402 7.96993 1.89034 8.01349 2.17755C8.05706 2.45953 8.07884 2.73107 8.07884 2.99217C8.07884 3.53003 7.98626 3.99739 7.80111 4.39426C7.61595 4.79112 7.37633 5.1201 7.08226 5.3812C6.78819 5.63708 6.45327 5.82768 6.07751 5.953C5.7072 6.07833 5.33416 6.14099 4.9584 6.14099C4.58809 6.14099 4.24772 6.09922 3.93731 6.01567C3.63235 5.92689 3.34644 5.8094 3.0796 5.66318C3.12861 6.11749 3.16673 6.56919 3.19396 7.01828C3.22119 7.46736 3.24025 7.94256 3.25114 8.44386C3.26203 8.93995 3.26748 9.47781 3.26748 10.0574C3.27293 10.6371 3.27293 11.2846 3.26748 12H1.25798V10.1044C1.25798 9.48825 1.24709 8.83812 1.2253 8.15405C1.20897 7.46475 1.15996 6.74151 1.07827 5.98433C0.996581 5.22715 0.871328 4.43342 0.702508 3.60313C0.533688 2.77285 0.299519 1.906 0 1.00261L1.93598 0.40731L2.2709 1.36292C2.29813 1.44125 2.34169 1.56658 2.4016 1.7389C2.46695 1.906 2.55136 2.09661 2.65483 2.3107C2.7583 2.51958 2.88083 2.73629 3.02242 2.96084C3.16946 3.18016 3.33827 3.38381 3.52888 3.5718C3.71948 3.75457 3.93187 3.906 4.16604 4.02611C4.40565 4.14099 4.66977 4.19843 4.9584 4.19843C5.02375 4.19843 5.11633 4.18799 5.23614 4.1671C5.36139 4.14621 5.48392 4.09661 5.60373 4.01828C5.72898 3.93473 5.8379 3.81201 5.93048 3.65013C6.02305 3.48825 6.06934 3.26893 6.06934 2.99217C6.06934 2.83029 6.05573 2.65535 6.0285 2.46736C6.00127 2.27415 5.96587 2.08877 5.92231 1.91123C5.88419 1.72846 5.84062 1.55875 5.79161 1.40209C5.74804 1.24021 5.7072 1.10444 5.66908 0.994778L7.59689 0.399477Z\" fill=\"#1C2D56\"/>\n<path d=\"M17.9907 4.62924C18.1432 4.62924 18.2929 4.62924 18.44 4.62924C18.587 4.62402 18.734 4.61619 18.8811 4.60574C19.0281 4.5953 19.1806 4.58224 19.3385 4.56658C19.5019 4.54569 19.6762 4.51958 19.8613 4.48825L20.3188 6.25065C20.0356 6.32898 19.7633 6.39687 19.5019 6.45431C19.2405 6.50653 18.9709 6.55091 18.6932 6.58747C18.4155 6.6188 18.1187 6.64491 17.8028 6.6658C17.4924 6.68146 17.1412 6.68929 16.7491 6.68929C16.1827 6.68929 15.6054 6.64752 15.0173 6.56397C14.4346 6.48042 13.8791 6.32898 13.3509 6.10966C13.3836 6.53264 13.4108 6.91906 13.4326 7.26893C13.4598 7.6188 13.4789 7.95039 13.4897 8.26371C13.5006 8.57702 13.5088 8.88251 13.5143 9.18016C13.5197 9.47781 13.5224 9.7859 13.5224 10.1044C13.5224 10.3238 13.5197 10.5483 13.5143 10.7781C13.5143 11.0026 13.5143 11.248 13.5143 11.5144V12H11.4884V11.5065C11.4884 10.7389 11.483 10.0209 11.4721 9.35248C11.4666 8.68407 11.4476 8.05222 11.4149 7.45692C11.3877 6.86162 11.3468 6.29243 11.2924 5.74935C11.2379 5.20627 11.1644 4.67363 11.0718 4.15144C10.9792 3.62924 10.8649 3.10966 10.7287 2.59269C10.5926 2.07572 10.4292 1.54569 10.2386 1.00261L12.1991 0.40731C12.2862 0.678851 12.3652 0.94778 12.436 1.2141C12.5122 1.48042 12.5857 1.75196 12.6565 2.02872C12.7001 2.18016 12.7382 2.33681 12.7709 2.49869C12.809 2.65535 12.8499 2.81201 12.8934 2.96867C12.9915 3.33943 13.1439 3.6423 13.3509 3.87728C13.5633 4.10705 13.792 4.27676 14.037 4.38642C14.0044 4.30809 13.969 4.22454 13.9309 4.13577C13.8927 4.047 13.8573 3.94778 13.8247 3.83812C13.7974 3.72324 13.7729 3.59791 13.7511 3.46214C13.7348 3.32637 13.7266 3.17493 13.7266 3.00783C13.7266 2.53264 13.8219 2.10966 14.0125 1.7389C14.2086 1.36292 14.4618 1.047 14.7722 0.791123C15.0881 0.530026 15.4421 0.334203 15.8342 0.203655C16.2317 0.067885 16.6292 0 17.0268 0C17.3426 0 17.634 0.0365535 17.9008 0.10966C18.1731 0.177546 18.4264 0.266318 18.6605 0.375979C18.8947 0.485639 19.1153 0.608355 19.3222 0.744125C19.5346 0.874673 19.7415 1.00261 19.943 1.12794L18.9791 2.78068C18.7885 2.65013 18.6088 2.53525 18.44 2.43603C18.2712 2.33159 18.1078 2.24543 17.9499 2.17755C17.7919 2.10966 17.6367 2.05744 17.4842 2.02089C17.3372 1.97911 17.1847 1.95561 17.0268 1.95039H16.9778C16.8362 1.95039 16.6837 1.97389 16.5203 2.02089C16.357 2.06788 16.2045 2.14099 16.0629 2.24021C15.9213 2.33942 15.8015 2.46214 15.7035 2.60835C15.6109 2.74935 15.5646 2.91123 15.5646 3.09399C15.5646 3.39164 15.6381 3.63969 15.7851 3.83812C15.9322 4.03655 16.1201 4.19582 16.3488 4.31593C16.583 4.43081 16.8444 4.51175 17.133 4.55875C17.4216 4.60574 17.7075 4.62924 17.9907 4.62924Z\" fill=\"#1C2D56\"/>\n</svg>\n",
"vuesax-linear:number-18": "<svg width=\"17\" height=\"14\" viewBox=\"0 0 17 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M1.05502 13.4129C1.05502 13.3105 1.05502 13.1901 1.05502 13.0516C1.05502 12.9131 1.05502 12.7686 1.05502 12.6181C1.05502 12.4675 1.05502 12.32 1.05502 12.1755C1.06084 12.031 1.06665 11.8985 1.07246 11.7781V11.7871C1.07827 11.4981 1.08118 11.2 1.08118 10.8929C1.08699 10.5798 1.0899 10.2516 1.0899 9.90839C1.0899 9.24602 1.08118 8.55957 1.06374 7.84903C1.05212 7.1385 1.01143 6.40086 0.941674 5.63613C0.87192 4.86538 0.764383 4.07054 0.619063 3.25161C0.473743 2.42667 0.267389 1.57161 0 0.686452L2.03157 0C2.32803 0.981505 2.55763 1.92387 2.72039 2.8271C2.88896 3.7243 3.01103 4.58538 3.0866 5.41032C3.16798 6.22925 3.21738 7.01505 3.23482 7.76774C3.25226 8.52043 3.26098 9.24301 3.26098 9.93548C3.26098 10.2787 3.25807 10.6099 3.25226 10.929C3.25226 11.2422 3.24935 11.5432 3.24354 11.8323C3.23773 11.9527 3.23192 12.0852 3.2261 12.2297C3.2261 12.3682 3.2261 12.5097 3.2261 12.6542C3.2261 12.7987 3.2261 12.9372 3.2261 13.0697C3.2261 13.2022 3.2261 13.3166 3.2261 13.4129H1.05502Z\" fill=\"#23493c\"/>\n<path d=\"M13.6693 6.05161C14.1052 7.3643 14.608 8.57763 15.1777 9.69161C15.7532 10.7996 16.3606 11.754 17 12.5548L15.3172 14C14.9684 13.5604 14.6226 13.0486 14.2796 12.4645C13.9425 11.8804 13.6082 11.2331 13.2769 10.5226C12.9456 9.80602 12.6201 9.03226 12.3004 8.20129C11.9806 7.37032 11.6639 6.48817 11.35 5.55484C11.1058 6.30753 10.8355 7.08129 10.5391 7.87613C10.2426 8.67097 9.92292 9.44473 9.57996 10.1974C9.24282 10.9441 8.89115 11.6456 8.52494 12.3019C8.15873 12.9523 7.78381 13.5123 7.40016 13.9819L5.69992 12.5548C6.008 12.1815 6.31317 11.748 6.61544 11.2542C6.9177 10.7604 7.21125 10.2335 7.49608 9.67355C7.7809 9.10753 8.0512 8.51742 8.30696 7.90323C8.56854 7.28903 8.80977 6.67183 9.03065 6.05161C9.19341 5.52774 9.35036 5.00086 9.50149 4.47097C9.65262 3.94108 9.78341 3.42925 9.89386 2.93548C10.0043 2.44172 10.0915 1.97806 10.1554 1.54452C10.2252 1.10495 10.2601 0.713549 10.2601 0.370324H12.4224C12.4224 0.737635 12.4515 1.13505 12.5096 1.56258C12.5736 1.99011 12.6578 2.44473 12.7625 2.92645C12.8729 3.40817 13.0037 3.91097 13.1548 4.43484C13.3118 4.95871 13.4833 5.49763 13.6693 6.05161Z\" fill=\"#23493c\"/>\n</svg>\n",
"vuesax-linear:number-24": "<svg width=\"21\" height=\"12\" viewBox=\"0 0 21 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M7.59689 0.399477C7.61323 0.446474 7.64862 0.558746 7.70308 0.736292C7.75754 0.913838 7.812 1.12794 7.86646 1.37859C7.92092 1.62402 7.96993 1.89034 8.01349 2.17755C8.05706 2.45953 8.07884 2.73107 8.07884 2.99217C8.07884 3.53003 7.98626 3.99739 7.80111 4.39426C7.61595 4.79112 7.37633 5.1201 7.08226 5.3812C6.78819 5.63708 6.45327 5.82768 6.07751 5.953C5.7072 6.07833 5.33416 6.14099 4.9584 6.14099C4.58809 6.14099 4.24772 6.09922 3.93731 6.01567C3.63235 5.92689 3.34644 5.8094 3.0796 5.66318C3.12861 6.11749 3.16673 6.56919 3.19396 7.01828C3.22119 7.46736 3.24025 7.94256 3.25114 8.44386C3.26203 8.93995 3.26748 9.47781 3.26748 10.0574C3.27293 10.6371 3.27293 11.2846 3.26748 12H1.25798V10.1044C1.25798 9.48825 1.24709 8.83812 1.2253 8.15405C1.20897 7.46475 1.15996 6.74151 1.07827 5.98433C0.996581 5.22715 0.871328 4.43342 0.702508 3.60313C0.533688 2.77285 0.299519 1.906 0 1.00261L1.93598 0.40731L2.2709 1.36292C2.29813 1.44125 2.34169 1.56658 2.4016 1.7389C2.46695 1.906 2.55136 2.09661 2.65483 2.3107C2.7583 2.51958 2.88083 2.73629 3.02242 2.96084C3.16946 3.18016 3.33827 3.38381 3.52888 3.5718C3.71948 3.75457 3.93187 3.906 4.16604 4.02611C4.40565 4.14099 4.66977 4.19843 4.9584 4.19843C5.02375 4.19843 5.11633 4.18799 5.23614 4.1671C5.36139 4.14621 5.48392 4.09661 5.60373 4.01828C5.72898 3.93473 5.8379 3.81201 5.93048 3.65013C6.02305 3.48825 6.06934 3.26893 6.06934 2.99217C6.06934 2.83029 6.05573 2.65535 6.0285 2.46736C6.00127 2.27415 5.96587 2.08877 5.92231 1.91123C5.88419 1.72846 5.84062 1.55875 5.79161 1.40209C5.74804 1.24021 5.7072 1.10444 5.66908 0.994778L7.59689 0.399477Z\" fill=\"#23493c\"/>\n<path d=\"M17.9907 4.62924C18.1432 4.62924 18.2929 4.62924 18.44 4.62924C18.587 4.62402 18.734 4.61619 18.8811 4.60574C19.0281 4.5953 19.1806 4.58224 19.3385 4.56658C19.5019 4.54569 19.6762 4.51958 19.8613 4.48825L20.3188 6.25065C20.0356 6.32898 19.7633 6.39687 19.5019 6.45431C19.2405 6.50653 18.9709 6.55091 18.6932 6.58747C18.4155 6.6188 18.1187 6.64491 17.8028 6.6658C17.4924 6.68146 17.1412 6.68929 16.7491 6.68929C16.1827 6.68929 15.6054 6.64752 15.0173 6.56397C14.4346 6.48042 13.8791 6.32898 13.3509 6.10966C13.3836 6.53264 13.4108 6.91906 13.4326 7.26893C13.4598 7.6188 13.4789 7.95039 13.4897 8.26371C13.5006 8.57702 13.5088 8.88251 13.5143 9.18016C13.5197 9.47781 13.5224 9.7859 13.5224 10.1044C13.5224 10.3238 13.5197 10.5483 13.5143 10.7781C13.5143 11.0026 13.5143 11.248 13.5143 11.5144V12H11.4884V11.5065C11.4884 10.7389 11.483 10.0209 11.4721 9.35248C11.4666 8.68407 11.4476 8.05222 11.4149 7.45692C11.3877 6.86162 11.3468 6.29243 11.2924 5.74935C11.2379 5.20627 11.1644 4.67363 11.0718 4.15144C10.9792 3.62924 10.8649 3.10966 10.7287 2.59269C10.5926 2.07572 10.4292 1.54569 10.2386 1.00261L12.1991 0.40731C12.2862 0.678851 12.3652 0.94778 12.436 1.2141C12.5122 1.48042 12.5857 1.75196 12.6565 2.02872C12.7001 2.18016 12.7382 2.33681 12.7709 2.49869C12.809 2.65535 12.8499 2.81201 12.8934 2.96867C12.9915 3.33943 13.1439 3.6423 13.3509 3.87728C13.5633 4.10705 13.792 4.27676 14.037 4.38642C14.0044 4.30809 13.969 4.22454 13.9309 4.13577C13.8927 4.047 13.8573 3.94778 13.8247 3.83812C13.7974 3.72324 13.7729 3.59791 13.7511 3.46214C13.7348 3.32637 13.7266 3.17493 13.7266 3.00783C13.7266 2.53264 13.8219 2.10966 14.0125 1.7389C14.2086 1.36292 14.4618 1.047 14.7722 0.791123C15.0881 0.530026 15.4421 0.334203 15.8342 0.203655C16.2317 0.067885 16.6292 0 17.0268 0C17.3426 0 17.634 0.0365535 17.9008 0.10966C18.1731 0.177546 18.4264 0.266318 18.6605 0.375979C18.8947 0.485639 19.1153 0.608355 19.3222 0.744125C19.5346 0.874673 19.7415 1.00261 19.943 1.12794L18.9791 2.78068C18.7885 2.65013 18.6088 2.53525 18.44 2.43603C18.2712 2.33159 18.1078 2.24543 17.9499 2.17755C17.7919 2.10966 17.6367 2.05744 17.4842 2.02089C17.3372 1.97911 17.1847 1.95561 17.0268 1.95039H16.9778C16.8362 1.95039 16.6837 1.97389 16.5203 2.02089C16.357 2.06788 16.2045 2.14099 16.0629 2.24021C15.9213 2.33942 15.8015 2.46214 15.7035 2.60835C15.6109 2.74935 15.5646 2.91123 15.5646 3.09399C15.5646 3.39164 15.6381 3.63969 15.7851 3.83812C15.9322 4.03655 16.1201 4.19582 16.3488 4.31593C16.583 4.43081 16.8444 4.51175 17.133 4.55875C17.4216 4.60574 17.7075 4.62924 17.9907 4.62924Z\" fill=\"#23493c\"/>\n</svg>\n",
"vuesax-linear:heart-fill": "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M16.44 3.09998C14.63 3.09998 13.01 3.97998 12 5.32998C10.99 3.97998 9.37 3.09998 7.56 3.09998C4.49 3.09998 2 5.59998 2 8.68998C2 9.87998 2.19 10.98 2.52 12C4.1 17 8.97 19.99 11.38 20.81C11.72 20.93 12.28 20.93 12.62 20.81C15.03 19.99 19.9 17 21.48 12C21.81 10.98 22 9.87998 22 8.68998C22 5.59998 19.51 3.09998 16.44 3.09998Z\" fill=\"#8D6A46\"/>\n</svg>\n",
"vuesax-linear:usd-coins": "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M7.1 16.8999C9.8 19.5999 14.3 19.5999 17 16.8999\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M16.9 7.09995C14.2 4.39995 9.69999 4.39995 6.99999 7.09995\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12Z\" stroke=\"#17191C\" stroke-width=\"1.5\" stroke-miterlimit=\"10\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>\n",
"vuesax-linear:heart-transparent": "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M12.62 20.81C12.28 20.93 11.72 20.93 11.38 20.81C8.48 19.82 2 15.69 2 8.68998C2 5.59998 4.49 3.09998 7.56 3.09998C9.38 3.09998 10.99 3.97998 12 5.33998C13.01 3.97998 14.63 3.09998 16.44 3.09998C19.51 3.09998 22 5.59998 22 8.68998C22 15.69 15.52 19.82 12.62 20.81Z\" fill=\"white\" fill-opacity=\"0.01\" stroke=\"#8D6A46\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>\n",
"vuesax-linear:shield_dollar": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\">\n<path d=\"M10.49 2.23L5.49997 4.11C4.34997 4.54 3.40997 5.9 3.40997 7.12V14.55C3.40997 15.73 4.18997 17.28 5.13997 17.99L9.43997 21.2C10.85 22.26 13.17 22.26 14.58 21.2L18.88 17.99C19.83 17.28 20.61 15.73 20.61 14.55V7.12C20.61 5.89 19.67 4.53 18.52 4.1L13.53 2.23C12.68 1.92 11.32 1.92 10.49 2.23Z\" stroke=\"#1C2D56\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M9 13.4905C9 14.4976 9.78333 15.281 10.7905 15.281H12.6929C13.4762 15.281 14.2595 14.6095 14.2595 13.7143C14.2595 12.7071 13.8119 12.3714 13.2524 12.1476L10.119 11.0286C9.33571 10.9167 9 10.581 9 9.68572C9 8.79048 9.67143 8.11905 10.5667 8.11905H12.581C13.5881 8.11905 14.3714 8.90238 14.3714 9.90952\" stroke=\"#1C2D56\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M11.5739 7V16.4\" stroke=\"#1C2D56\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>\n"
"vuesax-linear:shield_dollar": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\">\n<path d=\"M10.49 2.23L5.49997 4.11C4.34997 4.54 3.40997 5.9 3.40997 7.12V14.55C3.40997 15.73 4.18997 17.28 5.13997 17.99L9.43997 21.2C10.85 22.26 13.17 22.26 14.58 21.2L18.88 17.99C19.83 17.28 20.61 15.73 20.61 14.55V7.12C20.61 5.89 19.67 4.53 18.52 4.1L13.53 2.23C12.68 1.92 11.32 1.92 10.49 2.23Z\" stroke=\"#23493c\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M9 13.4905C9 14.4976 9.78333 15.281 10.7905 15.281H12.6929C13.4762 15.281 14.2595 14.6095 14.2595 13.7143C14.2595 12.7071 13.8119 12.3714 13.2524 12.1476L10.119 11.0286C9.33571 10.9167 9 10.581 9 9.68572C9 8.79048 9.67143 8.11905 10.5667 8.11905H12.581C13.5881 8.11905 14.3714 8.90238 14.3714 9.90952\" stroke=\"#23493c\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M11.5739 7V16.4\" stroke=\"#23493c\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>\n"
}
@@ -161,7 +161,7 @@ const wageLabel = computed(() => {
font-size: 10px;
font-weight: 700;
color: #fff;
background: @ink;
background: @primary;
}
.pc__flag--soft {
@@ -273,11 +273,6 @@
</Transition>
</Teleport>
<NotifyVant :timeOut="3000" v-model="notify" :color="'background-color: #14161A'">
<div class="font-bold text-right mb-2">ثبت سفارش</div>
<div>محصول با موفقیت به سبد خرید افزوده شد</div>
</NotifyVant>
<DialogVant :timeOut="-1" v-model:show="loginNotify" :closeOnClickOverlay="true">
<template v-slot:img>
<img :src="loginDialogImage" alt="" class="opacity-80" />
@@ -301,7 +296,7 @@ import { useRouter } from 'vue-router'
import Icon from '../icon/Icon.vue'
import GallerySlider from './GallerySlider.vue'
import Spinner from '../Spinner.vue'
import NotifyVant from '../NotifyVant.vue'
import { toast } from '../../composables/useToast'
import DialogVant from '../DialogVant.vue'
import { useProduct, isVariantOrderable } from '../../composables/useProduct'
import { useProductDetail } from '../../composables/useProductDetail'
@@ -327,7 +322,6 @@ const close = () => {
if (router.currentRoute.value.name === 'singleProduct') router.back()
}
const notify = ref(false)
const loginNotify = ref(false)
const imageIndex = ref(0)
const bodyOpen = ref(false)
@@ -484,7 +478,7 @@ const addToCart = () => {
// Previously the "added to cart" toast fired either way, telling the customer
// something had been added when nothing had. Kept in step with user-app-v2.
if (!cart.addToCart(storeProduct.value)) return
notify.value = true
toast.success('محصول با موفقیت به سبد خرید افزوده شد', { title: 'ثبت سفارش' })
}
const toggleFav = (e: Event) => {
@@ -732,8 +726,8 @@ onBeforeUnmount(() => {
transition: border-color 0.18s ease, background 0.18s ease;
}
.pd__variant.is-on {
background: @ink;
border-color: @ink;
background: @primary;
border-color: @primary;
}
.pd__variantImg {
width: 100%;
@@ -931,7 +925,7 @@ onBeforeUnmount(() => {
font-weight: 800;
text-decoration: none;
color: #fff;
background: @ink;
background: @primary;
transition: transform 0.18s ease, opacity 0.18s ease;
}
.pd__cta:active {
@@ -942,9 +936,9 @@ onBeforeUnmount(() => {
opacity: 0.45;
}
.pd__cta--ghost {
color: @ink;
color: @primary;
background: @canvas;
border: 1px solid @ink;
border: 1px solid @primary;
}
/* ── Full-screen preview ─────────────────────────────────── */
@@ -186,8 +186,8 @@ const closeFilters = (sendQuery: boolean): void => {
.filt__chip.is-on {
color: #fff;
background: @ink;
border-color: @ink;
background: @primary;
border-color: @primary;
}
.filt__chip:active {
@@ -280,7 +280,7 @@ const closeFilters = (sendQuery: boolean): void => {
.filt__apply {
color: #fff;
background: @ink;
background: @primary;
}
.filt__clear:active,
@@ -0,0 +1,325 @@
<!--
One toast: a glass card in the same family as the bottom nav — a square
icon tile on the start side, title + message, and a thin countdown line.
The countdown is a CSS animation; its `animationend` is what closes the
toast, so pausing it (finger held on the card) pauses the timer too, with
no JS clock to keep in sync. Swipe sideways or up to throw it away.
-->
<template>
<div
class="toast"
:class="[`toast--${item.type}`, { 'is-held': held, 'is-dragging': dragging }]"
:style="dragStyle"
role="status"
@pointerdown="onDown"
@pointermove="onMove"
@pointerup="onUp"
@pointercancel="onUp"
>
<span class="toast__tile" aria-hidden="true">
<span class="toast__ripple" />
<Icon :icon="item.icon" size="22" />
</span>
<div class="toast__body">
<div v-if="item.title" class="toast__title">{{ item.title }}</div>
<div class="toast__message">{{ item.message }}</div>
</div>
<span
v-if="item.duration > 0"
class="toast__progress"
:style="{ animationDuration: `${item.duration}ms` }"
@animationend="emit('close')"
/>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import Icon from '../icon/Icon.vue'
import type { ToastItem } from '../../composables/useToast'
defineProps<{ item: ToastItem }>()
const emit = defineEmits<{ (e: 'close'): void }>()
// A drag past either threshold dismisses; anything shorter springs back.
const SWIPE_X = 80
const SWIPE_UP = 36
const held = ref(false)
const dragging = ref(false)
const dx = ref(0)
const dy = ref(0)
let startX = 0
let startY = 0
const flung = ref(false)
let downAt = 0
const dragStyle = computed(() => {
if (flung.value) {
return {
transform: `translate(${dx.value}px, ${dy.value}px)`,
opacity: '0',
transition: 'transform 0.22s ease-in, opacity 0.22s ease-in',
}
}
if (!dragging.value) return undefined
// Upward drags follow the finger; downward ones are damped so the card
// only stretches a little, like pulling on something anchored at the top.
const y = dy.value < 0 ? dy.value : dy.value * 0.25
const fade = 1 - Math.min(Math.abs(dx.value) / 220, 0.6)
return {
transform: `translate(${dx.value}px, ${y}px) rotate(${dx.value * 0.03}deg)`,
opacity: String(fade),
transition: 'none',
}
})
function onDown(e: PointerEvent) {
held.value = true
startX = e.clientX
startY = e.clientY
downAt = Date.now()
;(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId)
}
function onMove(e: PointerEvent) {
if (!held.value) return
dx.value = e.clientX - startX
dy.value = e.clientY - startY
if (!dragging.value && Math.hypot(dx.value, dy.value) > 6) dragging.value = true
}
function onUp() {
held.value = false
if (!dragging.value) {
// A quick tap closes it; a long hold was only pausing it to read.
if (Date.now() - downAt < 250) emit('close')
return
}
if (Math.abs(dx.value) > SWIPE_X || dy.value < -SWIPE_UP) {
flung.value = true
dx.value = Math.abs(dx.value) > SWIPE_X ? Math.sign(dx.value) * window.innerWidth : dx.value
dy.value = dy.value < -SWIPE_UP ? -160 : dy.value
dragging.value = false
setTimeout(() => emit('close'), 200)
return
}
dragging.value = false
dx.value = 0
dy.value = 0
}
</script>
<style scoped lang="less">
.toast {
--accent: @wine;
position: relative;
display: flex;
align-items: center;
gap: 12px;
width: 100%;
padding: 10px 10px 12px 14px;
border-radius: 20px;
overflow: hidden;
pointer-events: auto;
touch-action: none;
cursor: grab;
transition: transform 0.45s cubic-bezier(0.2, 1.4, 0.4, 1), opacity 0.3s ease;
// Same glass recipe as the bottom nav, so the two read as one system.
background:
radial-gradient(120% 160% at 0% 0%, fade(@canvas, 60%) 0%, fade(@canvas, 0%) 55%),
radial-gradient(80% 140% at 100% 100%, fade(@ink, 4%) 0%, fade(@ink, 0%) 60%),
linear-gradient(160deg, fade(@canvas, 72%) 0%, fade(@canvas, 50%) 100%);
-webkit-backdrop-filter: blur(24px) saturate(200%) brightness(1.05);
backdrop-filter: blur(24px) saturate(200%) brightness(1.05);
box-shadow:
inset 0 1px 1px fade(@canvas, 90%),
inset 0 0 0 0.5px fade(@canvas, 40%),
0 18px 40px -16px rgba(20, 22, 26, 0.35),
0 1px 3px rgba(20, 22, 26, 0.06);
// Edge light, masked to a 1px ring.
&::after {
content: '';
position: absolute;
inset: 0;
padding: 1px;
border-radius: inherit;
background: linear-gradient(
145deg,
fade(@canvas, 100%) 0%,
fade(@canvas, 30%) 40%,
fade(@canvas, 10%) 70%,
fade(@canvas, 70%) 100%
);
-webkit-mask:
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
}
&.is-held:not(.is-dragging) {
transform: scale(0.98);
}
&.is-dragging {
cursor: grabbing;
}
}
.toast--success {
--accent: @green;
}
.toast--error {
--accent: @red;
}
.toast--warning {
--accent: @secondary;
}
.toast--info {
--accent: @wine;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.toast {
background: fade(@canvas, 96%);
}
}
// Square rounded tile — the same shape as the nav tiles — tinted by type.
.toast__tile {
position: relative;
flex: 0 0 42px;
display: flex;
align-items: center;
justify-content: center;
width: 42px;
height: 42px;
border-radius: 14px;
color: var(--accent);
background: color-mix(in srgb, var(--accent) 12%, transparent);
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 16%, transparent);
:deep(svg) {
position: relative;
animation: toast-icon-pop 0.6s 0.12s cubic-bezier(0.2, 1.6, 0.4, 1) both;
}
}
// A ring that pulses out of the tile once as the toast lands.
.toast__ripple {
position: absolute;
inset: 0;
border-radius: inherit;
border: 2px solid var(--accent);
opacity: 0;
animation: toast-ripple 0.9s 0.2s ease-out both;
}
.toast--error .toast__tile :deep(svg) {
animation:
toast-icon-pop 0.6s 0.12s cubic-bezier(0.2, 1.6, 0.4, 1) both,
toast-shake 0.45s 0.55s ease-in-out;
}
.toast__body {
flex: 1;
min-width: 0;
text-align: right;
}
.toast__title {
margin-bottom: 2px;
font-size: 13px;
font-weight: 700;
line-height: 1.5;
color: @ink;
}
.toast__message {
font-size: 12.5px;
font-weight: 500;
line-height: 1.6;
color: @inkSoft;
}
// Countdown line along the bottom, draining toward the start side.
.toast__progress {
position: absolute;
right: 14px;
left: 14px;
bottom: 5px;
height: 2.5px;
border-radius: 2px;
background: var(--accent);
opacity: 0.55;
transform-origin: right center;
animation-name: toast-drain;
animation-timing-function: linear;
animation-fill-mode: forwards;
}
.toast.is-held .toast__progress {
animation-play-state: paused;
}
@keyframes toast-drain {
from {
transform: scaleX(1);
}
to {
transform: scaleX(0);
}
}
@keyframes toast-icon-pop {
0% {
transform: scale(0) rotate(-30deg);
opacity: 0;
}
100% {
transform: scale(1) rotate(0);
opacity: 1;
}
}
@keyframes toast-ripple {
0% {
transform: scale(1);
opacity: 0.5;
}
100% {
transform: scale(1.6);
opacity: 0;
}
}
@keyframes toast-shake {
0%,
100% {
transform: translateX(0);
}
20%,
60% {
transform: translateX(-3px);
}
40%,
80% {
transform: translateX(3px);
}
}
@media (prefers-reduced-motion: reduce) {
.toast__tile :deep(svg),
.toast__ripple {
animation: none !important;
}
}
</style>
@@ -0,0 +1,89 @@
<!--
Renders the shared toast queue (see composables/useToast.ts). Mounted once
in App.vue. Toasts drop in from the top with a spring, the stack slides to
make room, and a closing toast shrinks up and fades out.
-->
<template>
<Teleport to="body">
<div class="toast-host">
<TransitionGroup name="toast">
<ToastCard v-for="item in toasts" :key="item.id" :item="item" @close="dismiss(item.id)" />
</TransitionGroup>
</div>
</Teleport>
</template>
<script setup lang="ts">
import ToastCard from './ToastCard.vue'
import { useToast } from '../../composables/useToast'
const { toasts, dismiss } = useToast()
</script>
<style lang="less">
.toast-host {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 3000;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: calc(12px + env(safe-area-inset-top, 0px)) 14px 0;
direction: rtl;
pointer-events: none;
> * {
max-width: 420px;
}
}
// Enter: drop from above, slightly small and blurred, then overshoot into place.
.toast-host .toast.toast-enter-active {
transition:
transform 0.6s cubic-bezier(0.2, 1.35, 0.4, 1),
opacity 0.35s ease,
filter 0.4s ease;
}
.toast-host .toast.toast-enter-from {
transform: translateY(-120%) scale(0.88);
opacity: 0;
filter: blur(6px);
}
// Leave: taken out of flow so the stack can glide up behind it.
.toast-host .toast.toast-leave-active {
position: absolute;
left: 14px;
right: 14px;
margin: 0 auto;
transition:
transform 0.32s cubic-bezier(0.5, 0, 0.75, 0),
opacity 0.28s ease,
filter 0.3s ease;
}
.toast-host .toast.toast-leave-to {
transform: translateY(-40%) scale(0.9);
opacity: 0;
filter: blur(4px);
}
.toast-host .toast.toast-move {
transition: transform 0.45s cubic-bezier(0.2, 1.2, 0.4, 1);
}
@media (prefers-reduced-motion: reduce) {
.toast-host .toast.toast-enter-active,
.toast-host .toast.toast-leave-active,
.toast-host .toast.toast-move {
transition: opacity 0.2s ease;
}
.toast-host .toast.toast-enter-from,
.toast-host .toast.toast-leave-to {
transform: none;
filter: none;
}
}
</style>