first commit
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { $themeConfig } from '@/theme.config'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { useAppStore, type LocaleCode } from '@/stores/app'
|
||||
|
||||
export default {
|
||||
init() {
|
||||
@@ -32,7 +32,7 @@ export default {
|
||||
store.toggleSemidark(value === 'true' ? true : $themeConfig.semidark)
|
||||
},
|
||||
|
||||
toggleLanguage(item?: { code: string; name: string }) {
|
||||
toggleLanguage(item?: { code: LocaleCode; name: string }) {
|
||||
const store = useAppStore()
|
||||
const lang = item || store.languageList.find((entry) => entry.code === store.locale) || store.languageList[0]
|
||||
store.toggleLocale(lang.code)
|
||||
|
||||
@@ -490,6 +490,7 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import type { ApexOptions } from 'apexcharts';
|
||||
import apexchart from 'vue3-apexcharts';
|
||||
import { useAppStore } from '@/stores/app';
|
||||
import { useMeta } from '@/composables/use-meta';
|
||||
@@ -546,7 +547,7 @@
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakPoint: 576,
|
||||
breakpoint: 576,
|
||||
options: {
|
||||
chart: {
|
||||
height: 95,
|
||||
@@ -561,7 +562,7 @@
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
} as ApexOptions;
|
||||
});
|
||||
|
||||
const bitcoinSeries = ref([
|
||||
@@ -608,7 +609,7 @@
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakPoint: 576,
|
||||
breakpoint: 576,
|
||||
options: {
|
||||
chart: {
|
||||
height: 95,
|
||||
@@ -623,7 +624,7 @@
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
} as ApexOptions;
|
||||
});
|
||||
|
||||
const ethereumSeries = ref([
|
||||
@@ -670,7 +671,7 @@
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakPoint: 576,
|
||||
breakpoint: 576,
|
||||
options: {
|
||||
chart: {
|
||||
height: 95,
|
||||
@@ -685,7 +686,7 @@
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
} as ApexOptions;
|
||||
});
|
||||
|
||||
const litecoinSeries = ref([
|
||||
@@ -732,7 +733,7 @@
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakPoint: 576,
|
||||
breakpoint: 576,
|
||||
options: {
|
||||
chart: {
|
||||
height: 95,
|
||||
@@ -747,7 +748,7 @@
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
} as ApexOptions;
|
||||
});
|
||||
|
||||
const binanceSeries = ref([
|
||||
@@ -794,7 +795,7 @@
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakPoint: 576,
|
||||
breakpoint: 576,
|
||||
options: {
|
||||
chart: {
|
||||
height: 95,
|
||||
@@ -809,7 +810,7 @@
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
} as ApexOptions;
|
||||
});
|
||||
|
||||
const tetherSeries = ref([
|
||||
@@ -856,7 +857,7 @@
|
||||
},
|
||||
responsive: [
|
||||
{
|
||||
breakPoint: 576,
|
||||
breakpoint: 576,
|
||||
options: {
|
||||
chart: {
|
||||
height: 95,
|
||||
@@ -871,7 +872,7 @@
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
} as ApexOptions;
|
||||
});
|
||||
|
||||
const solanaSeries = ref([
|
||||
|
||||
@@ -747,6 +747,7 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import type { ApexOptions } from 'apexcharts';
|
||||
import apexchart from 'vue3-apexcharts';
|
||||
|
||||
import { useAppStore } from '@/stores/app';
|
||||
@@ -907,7 +908,7 @@
|
||||
stops: isDark ? [100, 100] : [45, 100],
|
||||
},
|
||||
},
|
||||
};
|
||||
} as ApexOptions;
|
||||
});
|
||||
|
||||
const revenueSeries = ref([
|
||||
@@ -936,7 +937,7 @@
|
||||
stroke: {
|
||||
show: true,
|
||||
width: 25,
|
||||
colors: isDark ? '#0e1726' : '#fff',
|
||||
colors: isDark ? ['#0e1726'] : ['#fff'],
|
||||
},
|
||||
colors: isDark ? ['#5c1ac3', '#e2a03f', '#e7515a', '#e2a03f'] : ['#e2a03f', '#5c1ac3', '#e7515a'],
|
||||
legend: {
|
||||
@@ -1002,7 +1003,7 @@
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
} as ApexOptions;
|
||||
});
|
||||
|
||||
const salesByCategorySeries = ref([985, 737, 270]);
|
||||
@@ -1076,7 +1077,7 @@
|
||||
left: -20,
|
||||
},
|
||||
},
|
||||
};
|
||||
} as ApexOptions;
|
||||
});
|
||||
|
||||
const dailySalesSeries = ref([
|
||||
@@ -1137,7 +1138,7 @@
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
} as ApexOptions;
|
||||
});
|
||||
|
||||
const totalOrdersSeries = ref([
|
||||
|
||||
12
src/env.d.ts
vendored
12
src/env.d.ts
vendored
@@ -5,3 +5,15 @@ declare module '*.vue' {
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
|
||||
declare module 'vue-height-collapsible/vue3' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
|
||||
declare module 'vue-height-collapsible/vue3/vue-height-collapsible.esm.js' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ import type {
|
||||
} from '@/types/product'
|
||||
|
||||
type QueryPrimitive = string | number | boolean | null | undefined
|
||||
type QueryValue = QueryPrimitive | string[] | ProductAttributes | ProductAttributeAssignment[] | ProductMeta | Record<string, unknown>
|
||||
export type QueryValue = QueryPrimitive | string[] | ProductAttributes | ProductAttributeAssignment[] | ProductMeta | Record<string, unknown>
|
||||
|
||||
export const buildQueryParams = (params: Record<string, QueryValue>) => {
|
||||
export const buildQueryParams = (params: Record<string, unknown>) => {
|
||||
const query: Record<string, string | number | boolean> = {}
|
||||
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
@@ -24,19 +24,19 @@ export const buildQueryParams = (params: Record<string, QueryValue>) => {
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
if (value.length > 0) {
|
||||
query[key] = JSON.stringify(value)
|
||||
query[key] = JSON.stringify(value as QueryValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
if (Object.keys(value).length > 0) {
|
||||
query[key] = JSON.stringify(value)
|
||||
query[key] = JSON.stringify(value as QueryValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
query[key] = value
|
||||
query[key] = value as string | number | boolean
|
||||
})
|
||||
|
||||
return query
|
||||
|
||||
@@ -47,7 +47,7 @@ class ApiService {
|
||||
if (refreshToken) {
|
||||
try {
|
||||
const response = await this.refreshToken({ refreshToken })
|
||||
const { accessToken, refreshToken: newRefreshToken } = response.data
|
||||
const { accessToken, refreshToken: newRefreshToken } = response
|
||||
|
||||
localStorage.setItem('accessToken', accessToken)
|
||||
localStorage.setItem('refreshToken', newRefreshToken)
|
||||
|
||||
@@ -3,6 +3,7 @@ import i18n from '@/i18n'
|
||||
import appSetting from '@/app-setting'
|
||||
|
||||
const rtlLanguages = new Set(['ae', 'fa', 'ar'])
|
||||
export type LocaleCode = 'fa' | 'ae' | 'en'
|
||||
|
||||
export const useAppStore = defineStore('app', {
|
||||
state: () => ({
|
||||
@@ -13,13 +14,13 @@ export const useAppStore = defineStore('app', {
|
||||
rtlClass: 'rtl',
|
||||
animation: '',
|
||||
navbar: 'navbar-sticky',
|
||||
locale: 'fa',
|
||||
locale: 'fa' as LocaleCode,
|
||||
sidebar: false,
|
||||
languageList: [
|
||||
{ code: 'fa', name: 'فارسی' },
|
||||
{ code: 'ae', name: 'Arabic' },
|
||||
{ code: 'en', name: 'English' },
|
||||
],
|
||||
] as Array<{ code: LocaleCode; name: string }>,
|
||||
isShowMainLoader: true,
|
||||
semidark: false,
|
||||
}),
|
||||
@@ -81,7 +82,7 @@ export const useAppStore = defineStore('app', {
|
||||
this.semidark = value
|
||||
},
|
||||
|
||||
toggleLocale(payload: string | null = null) {
|
||||
toggleLocale(payload: LocaleCode | null = null) {
|
||||
const value = payload || this.locale
|
||||
i18n.global.locale.value = value
|
||||
localStorage.setItem('i18n_locale', value)
|
||||
|
||||
@@ -209,7 +209,7 @@ export interface ProductFormPayload {
|
||||
brandId?: string
|
||||
brand: string
|
||||
basePriceUSD: number
|
||||
salePriceUSD?: number | null
|
||||
salePriceUSD?: number | null | ''
|
||||
stock: number
|
||||
featured: boolean
|
||||
type: ProductType
|
||||
|
||||
@@ -139,8 +139,9 @@ export const normalizeAttributes = (attributes?: Record<string, unknown> | Produ
|
||||
}, {})
|
||||
}
|
||||
|
||||
export const attributesToEntries = (attributes?: ProductAttributes): AttributeEntry[] => {
|
||||
const entries = Object.entries(attributes || {}).map(([key, value]) => ({
|
||||
export const attributesToEntries = (attributes?: ProductAttributes | ProductAttributeAssignment[]): AttributeEntry[] => {
|
||||
const normalizedAttributes = normalizeAttributes(attributes)
|
||||
const entries = Object.entries(normalizedAttributes).map(([key, value]) => ({
|
||||
key,
|
||||
value: value === null || value === undefined ? '' : String(value),
|
||||
}))
|
||||
@@ -263,7 +264,7 @@ export const normalizeEnglishSlug = (value: string) =>
|
||||
|
||||
export const generateEnglishSlug = (value: string) => normalizeEnglishSlug(transliteratePersianToLatin(value))
|
||||
|
||||
export const formatCurrency = (value?: number | null) => {
|
||||
export const formatCurrency = (value?: number | null | '') => {
|
||||
const safeValue = Number(value || 0)
|
||||
return new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
|
||||
@@ -202,6 +202,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
import apexchart from 'vue3-apexcharts'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import IconHorizontalDots from '@/components/icon/icon-horizontal-dots.vue'
|
||||
@@ -399,7 +400,7 @@ const revenueChart = computed(() => {
|
||||
stops: [40, 100],
|
||||
},
|
||||
},
|
||||
}
|
||||
} as ApexOptions
|
||||
})
|
||||
|
||||
const salesByCategory = computed(() => {
|
||||
@@ -446,7 +447,7 @@ const salesByCategory = computed(() => {
|
||||
hover: { filter: { type: 'none', value: 0.15 } },
|
||||
active: { filter: { type: 'none', value: 0.15 } },
|
||||
},
|
||||
}
|
||||
} as ApexOptions
|
||||
})
|
||||
|
||||
const dailySales = computed(() => ({
|
||||
@@ -478,7 +479,7 @@ const dailySales = computed(() => ({
|
||||
formatter: (value: number) => `${value} سفارش`,
|
||||
},
|
||||
},
|
||||
}))
|
||||
} as ApexOptions))
|
||||
|
||||
const inventoryChart = computed(() => ({
|
||||
chart: {
|
||||
@@ -510,5 +511,5 @@ const inventoryChart = computed(() => ({
|
||||
formatter: (value: number) => `${value} SKU`,
|
||||
},
|
||||
},
|
||||
}))
|
||||
} as ApexOptions))
|
||||
</script>
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
v-model="form.slug"
|
||||
type="text"
|
||||
dir="ltr"
|
||||
inputmode="latin"
|
||||
inputmode="text"
|
||||
class="form-input"
|
||||
placeholder="skf"
|
||||
@input="sanitizeSlugInput"
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
v-model="form.slug"
|
||||
type="text"
|
||||
dir="ltr"
|
||||
inputmode="latin"
|
||||
inputmode="text"
|
||||
class="form-input"
|
||||
placeholder="bolbering-sanati"
|
||||
@input="sanitizeSlugInput"
|
||||
|
||||
@@ -127,7 +127,7 @@ const errors = reactive({
|
||||
const errorMessage = ref('')
|
||||
const countdown = ref(120) // 2 minutes
|
||||
const isResending = ref(false)
|
||||
let countdownInterval: NodeJS.Timeout | null = null
|
||||
let countdownInterval: ReturnType<typeof setInterval> | null = null
|
||||
|
||||
const phone = ref(sessionStorage.getItem('otpPhone') || '')
|
||||
const fullName = ref(sessionStorage.getItem('otpFullName') || '')
|
||||
|
||||
Reference in New Issue
Block a user