create landing page for boursemes

This commit is contained in:
2026-08-01 10:11:28 +03:30
commit 4cc5ca6b5c
150 changed files with 18714 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
VITE_LOGIN_APP_URL=https://boursemes.com/home
+5
View File
@@ -0,0 +1,5 @@
node_modules
dist
.DS_Store
*.local
.env
+16
View File
@@ -0,0 +1,16 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
declare module 'vue' {
export interface GlobalComponents {
BasicButton: typeof import('./src/components/BasicPacks/BasicButton.vue')['default']
BasicIcon: typeof import('./src/components/BasicPacks/BasicIcon.vue')['default']
BasicModal: typeof import('./src/components/BasicPacks/BasicModal.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}
}
Vendored
+9
View File
@@ -0,0 +1,9 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_LOGIN_APP_URL: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
+751
View File
@@ -0,0 +1,751 @@
<!doctype html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8" />
<meta name="enamad" content="44889195" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover, interactive-widget=resizes-content"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<title>در حال بارگذاری...</title>
<!---->
<style>
:root {
--boot-bg: #133050;
--boot-bg-soft: #133050;
--boot-card: rgba(255, 255, 255, 0.88);
--boot-border: rgba(15, 23, 42, 0.08);
--boot-text: #111827;
--boot-muted: rgba(15, 23, 42, 0.62);
--boot-accent: #2563eb;
--boot-orb: rgba(37, 99, 235, 0.10);
--boot-spinner-track: rgba(15, 23, 42, 0.10);
--boot-shadow: rgba(15, 23, 42, 0.10);
}
html,
body {
margin: 0;
min-height: 100%;
width: 100%;
background: var(--boot-bg);
}
#app {
min-height: 100vh;
width: 100%;
max-width: none;
}
.boot-loader {
min-height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
direction: rtl;
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif;
background: var(--boot-bg);
color: var(--boot-text);
overflow: hidden;
}
.boot-loader__logo {
width: min(72vw, 280px);
height: auto;
object-fit: contain;
animation: boot-logo-fade-in 0.45s ease-out both;
}
@keyframes boot-logo-fade-in {
from {
opacity: 0;
transform: scale(0.96);
}
to {
opacity: 1;
transform: scale(1);
}
}
/* Critical: full-viewport splash before Vue/CSS hydrate */
@media (min-width: 768px) {
html, body, #app {
width: 100%;
max-width: none;
}
body {
display: block !important;
}
}
#app,
.boot-loader {
width: 100% !important;
max-width: none !important;
}
.app-splash-screen {
position: fixed !important;
inset: 0 !important;
width: 100vw !important;
min-width: 100vw !important;
max-width: none !important;
min-height: 100vh !important;
left: 0 !important;
right: 0 !important;
margin: 0 !important;
transform: none !important;
z-index: 2147483646;
}
</style>
<script>
(function () {
if (window.matchMedia('(min-width: 768px)').matches) {
document.documentElement.classList.add('app-layout--desktop')
}
})()
</script>
<script>
;(function () {
var CONFIG_COOKIE_NAME = 'APP_CONFIG_CACHE'
function getCookie(name) {
var cookie = document.cookie.split('; ').find(function (row) {
return row.indexOf(name + '=') === 0
})
if (!cookie) return null
return cookie.substring(name.length + 1)
}
function readCachedConfig() {
try {
var rawCookie = getCookie(CONFIG_COOKIE_NAME)
if (!rawCookie) return null
var decoded = decodeURIComponent(rawCookie)
var payload = JSON.parse(decoded)
return payload && payload.config ? payload.config : null
} catch (error) {
console.warn('Boot theme: failed to read cached config', error)
return null
}
}
function normalizeHex(hex) {
if (!hex || typeof hex !== 'string') return null
var value = hex.trim()
if (!value) return null
if (value[0] !== '#') {
value = '#' + value
}
if (/^#[0-9a-fA-F]{3}$/.test(value)) {
value =
'#' +
value[1] +
value[1] +
value[2] +
value[2] +
value[3] +
value[3]
}
if (!/^#[0-9a-fA-F]{6}$/.test(value)) return null
return value
}
function hexToRgb(hex) {
var normalized = normalizeHex(hex)
if (!normalized) return null
var num = parseInt(normalized.slice(1), 16)
return {
r: (num >> 16) & 255,
g: (num >> 8) & 255,
b: num & 255
}
}
function rgbToHex(r, g, b) {
function toHex(value) {
var hex = Math.max(0, Math.min(255, Math.round(value))).toString(16)
return hex.length === 1 ? '0' + hex : hex
}
return '#' + toHex(r) + toHex(g) + toHex(b)
}
function mix(hexA, hexB, weight) {
var a = hexToRgb(hexA)
var b = hexToRgb(hexB)
if (!a || !b) return hexA
return rgbToHex(
a.r * (1 - weight) + b.r * weight,
a.g * (1 - weight) + b.g * weight,
a.b * (1 - weight) + b.b * weight
)
}
function brightness(hex) {
var rgb = hexToRgb(hex)
if (!rgb) return 0
return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000
}
function hexToRgba(hex, alpha) {
var rgb = hexToRgb(hex)
if (!rgb) return 'rgba(96, 165, 250, ' + alpha + ')'
return 'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + alpha + ')'
}
function setVar(name, value) {
document.documentElement.style.setProperty(name, value)
}
function applyBootTheme() {
var config = readCachedConfig()
var user = config && config.user ? config.user : null
if (!user) return
var tenantColor = normalizeHex(user.color)
var tenantSecondary = normalizeHex(user.secondary_color)
var tenantBackground = normalizeHex(user.background_color)
/**
* مهم:
* background_color بک‌گراند اپ است.
* اگر نبود، لودینگ باید روشن بماند، نه اینکه color را بک‌گراند کنیم.
*/
var bg = tenantBackground || '#ffffff'
/**
* color و secondary_color فقط برای accent استفاده می‌شوند.
*/
var accent = tenantSecondary || tenantColor || '#2563eb'
var isLight = brightness(bg) > 155
var bgSoft = isLight ? mix(bg, accent, 0.045) : mix(bg, '#ffffff', 0.055)
var text = isLight ? '#111827' : '#ffffff'
var muted = isLight ? 'rgba(15, 23, 42, 0.62)' : 'rgba(255, 255, 255, 0.70)'
var card = isLight ? 'rgba(255, 255, 255, 0.88)' : 'rgba(255, 255, 255, 0.07)'
var border = isLight ? 'rgba(15, 23, 42, 0.08)' : 'rgba(255, 255, 255, 0.12)'
var orb = hexToRgba(accent, isLight ? 0.10 : 0.18)
var spinnerTrack = isLight ? 'rgba(15, 23, 42, 0.10)' : 'rgba(255, 255, 255, 0.14)'
var shadow = isLight ? 'rgba(15, 23, 42, 0.10)' : 'rgba(0, 0, 0, 0.24)'
setVar('--boot-bg', bg)
setVar('--boot-bg-soft', bgSoft)
setVar('--boot-accent', accent)
setVar('--boot-text', text)
setVar('--boot-muted', muted)
setVar('--boot-card', card)
setVar('--boot-border', border)
setVar('--boot-orb', orb)
setVar('--boot-spinner-track', spinnerTrack)
setVar('--boot-shadow', shadow)
if (tenantColor) {
setVar('--App-primary-color', tenantColor)
}
if (tenantSecondary) {
setVar('--App-secondary-color', tenantSecondary)
}
if (tenantBackground) {
setVar('--App-background-color', tenantBackground)
}
var logoEl = document.getElementById('boot-logo')
if (logoEl) {
if (user.name === 'boursecu') {
logoEl.src = '/boursecu-splash.png'
} else if (user.avatar) {
logoEl.src = user.avatar
}
}
if (user.name === 'boursecu') {
setVar('--boot-bg', '#133050')
setVar('--boot-bg-soft', '#133050')
}
document.title = user.name_fa || user.name || 'در حال بارگذاری...'
}
applyBootTheme()
})()
</script>
</head>
<body>
<div id="app">
<div class="boot-loader">
<img
id="boot-logo"
class="boot-loader__logo"
src="/boursecu-splash.png"
alt=""
/>
</div>
</div>
<script>
;(function () {
var BOOT_TIMEOUT_MS = 90000
var RETRY_KEY = '__APP_BOOT_RETRY_CLICKED__'
var RECOVERY_KEY = '__APP_BOOT_RECOVERY_DONE__'
var CONFIG_COOKIE_NAME = 'APP_CONFIG_CACHE'
var CONFIG_COOKIE_MAX_AGE_SECONDS = 60 * 60 * 24 * 7
var TOKEN_STORAGE_KEY = 'customer_session_token'
var LEGACY_TOKEN_SUFFIX = '_app_token'
var VERSION_SUCCESS_URL_KEY = 'VERSION_Success_URL'
var VERSION_STORAGE_KEY = 'version'
var CONFIG_SUCCESS_URL_KEY = 'CONFIG_Success_URL'
function getProtocol() {
return window.location.protocol === 'https:' ? 'https:' : 'http:'
}
function getVersionUrls() {
var protocol = getProtocol()
return [
'https://nerkh.gold/get_version',
'https://tablo.talasevin.ir/get_version',
'https://abshode-service.montgit.ir/server/get_version',
protocol + '//212.23.201.173:8381/get_version',
protocol + '//91.212.174.137:4040/server/get_version'
]
}
function getConfigUrls() {
var protocol = getProtocol()
return [
protocol + '//nerkh.gold/get_user',
protocol + '//tablo.talasevin.ir/get_user',
protocol + '//abshode-service.montgit.ir/server/get_user',
protocol + '//212.23.201.173:8381/get_user',
protocol + '//91.212.174.137:4040/server/get_user'
]
}
function sortVersionUrls(urls) {
var lastSuccessUrl = localStorage.getItem(VERSION_SUCCESS_URL_KEY)
if (!lastSuccessUrl) {
return urls.slice()
}
return [lastSuccessUrl].concat(urls.filter(function (url) {
return url !== lastSuccessUrl
}))
}
function sortByLastSuccess(urls) {
var lastSuccessUrl = localStorage.getItem(CONFIG_SUCCESS_URL_KEY)
return urls.slice().sort(function (a, b) {
if (a === lastSuccessUrl) return -1
if (b === lastSuccessUrl) return 1
return 0
})
}
function normalizeVersionResponse(data) {
if (typeof data === 'string' || typeof data === 'number') {
return String(data).trim()
}
if (!data) return ''
if (typeof data.data === 'string' || typeof data.data === 'number') {
return String(data.data).trim()
}
var version =
data.version ||
data.value ||
(data.data && typeof data.data === 'object' ? data.data.version : '')
return version ? String(version).trim() : ''
}
async function fetchJsonOrText(url, timeout) {
var controller = new AbortController()
var timeoutId = window.setTimeout(function () {
controller.abort()
}, timeout)
try {
var response = await fetch(url, {
method: 'GET',
headers: {
Accept: 'application/json'
},
cache: 'no-store',
signal: controller.signal
})
if (!response.ok) {
throw new Error('Request failed: ' + response.status)
}
var contentType = response.headers.get('content-type') || ''
if (contentType.indexOf('application/json') !== -1) {
return await response.json()
}
return await response.text()
} finally {
window.clearTimeout(timeoutId)
}
}
async function fetchVersionFromUrl(url, timeout) {
var controller = new AbortController()
var timeoutId = window.setTimeout(function () {
controller.abort()
}, timeout)
try {
var response = await fetch(url, {
method: 'GET',
headers: {
Accept: 'application/json'
},
cache: 'no-store',
signal: controller.signal
})
if (!response.ok) {
throw new Error('Version request failed: ' + response.status)
}
var contentType = response.headers.get('content-type') || ''
var data
if (contentType.indexOf('application/json') !== -1) {
data = await response.json()
} else {
data = await response.text()
}
var version = normalizeVersionResponse(data)
if (!version) {
throw new Error('Version response is empty')
}
localStorage.setItem(VERSION_SUCCESS_URL_KEY, url)
return version
} catch (error) {
if (localStorage.getItem(VERSION_SUCCESS_URL_KEY) === url) {
localStorage.removeItem(VERSION_SUCCESS_URL_KEY)
}
console.warn('Version failed:', url, error)
return undefined
} finally {
window.clearTimeout(timeoutId)
}
}
async function loadRemoteVersion(rounds) {
var urls = sortVersionUrls(getVersionUrls())
for (var round = 1; round <= rounds; round++) {
for (var i = 0; i < urls.length; i++) {
var timeout = i === urls.length - 1 ? 6000 : 3500
var result = await fetchVersionFromUrl(urls[i], timeout)
if (result) {
return result
}
}
}
return null
}
async function fetchFreshConfig(rounds) {
var urls = sortByLastSuccess(getConfigUrls())
for (var round = 1; round <= rounds; round++) {
for (var i = 0; i < urls.length; i++) {
var url = urls[i]
try {
var config = await fetchJsonOrText(url, i === urls.length - 1 ? 7000 : 4000)
if (!config || typeof config !== 'object') {
throw new Error('Config response is invalid')
}
return {
config: config,
url: url
}
} catch (error) {
if (localStorage.getItem(CONFIG_SUCCESS_URL_KEY) === url) {
localStorage.removeItem(CONFIG_SUCCESS_URL_KEY)
}
console.warn('Config failed:', url, 'round:', round, error)
}
}
}
throw new Error('Cannot fetch fresh config')
}
function writeConfigCookie(config) {
try {
var payload = {
cached_at: Date.now(),
config: config
}
var encoded = encodeURIComponent(JSON.stringify(payload))
var secure = window.location.protocol === 'https:' ? '; Secure' : ''
document.cookie =
CONFIG_COOKIE_NAME +
'=' +
encoded +
'; Path=/; Max-Age=' +
CONFIG_COOKIE_MAX_AGE_SECONDS +
'; SameSite=Lax' +
secure
} catch (error) {
console.warn('Failed to write config cookie:', error)
}
}
function clearReadableCookies() {
document.cookie.split(';').forEach(function (cookie) {
var name = cookie.split('=')[0] && cookie.split('=')[0].trim()
if (!name) return
document.cookie = name + '=; Path=/; Max-Age=0; SameSite=Lax'
})
}
function collectAuthTokensForPreserve() {
var preserved = {}
var session = localStorage.getItem(TOKEN_STORAGE_KEY)
if (session) {
preserved[TOKEN_STORAGE_KEY] = session
}
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i)
if (!key) continue
if (key.length >= LEGACY_TOKEN_SUFFIX.length &&
key.slice(-LEGACY_TOKEN_SUFFIX.length) === LEGACY_TOKEN_SUFFIX) {
var value = localStorage.getItem(key)
if (value) {
preserved[key] = value
}
}
}
return preserved
}
function clearLocalStorageExceptToken() {
var preserved = collectAuthTokensForPreserve()
localStorage.clear()
Object.keys(preserved).forEach(function (key) {
localStorage.setItem(key, preserved[key])
})
}
async function clearServiceWorkersAndCaches() {
try {
if ('serviceWorker' in navigator) {
var registrations = await navigator.serviceWorker.getRegistrations()
await Promise.all(
registrations.map(function (registration) {
return registration.unregister()
})
)
}
} catch (error) {
console.warn('Failed to unregister service workers:', error)
}
try {
if ('caches' in window) {
var keys = await caches.keys()
await Promise.all(
keys.map(function (key) {
return caches.delete(key)
})
)
}
} catch (error) {
console.warn('Failed to clear caches:', error)
}
}
function reloadWithCacheBust() {
var url = new URL(window.location.href)
url.searchParams.set('__boot_recover', String(Date.now()))
window.location.replace(url.toString())
}
function renderRecovering(text) {
var app = document.getElementById('app')
if (!app) return
app.innerHTML =
'<div style="min-height: 100vh; display: flex; align-items: center; justify-content: center; direction: rtl; font-family: sans-serif; padding: 24px; background: var(--boot-bg); color: var(--boot-text);">' +
'<div style="width: min(420px, 100%); text-align: center; background: var(--boot-card); border: 1px solid var(--boot-border); border-radius: 24px; padding: 28px 22px;">' +
'<div style="width: 54px; height: 54px; margin: 0 auto 18px; border-radius: 999px; border: 4px solid rgba(255,255,255,0.18); border-top-color: var(--boot-accent); animation: bootSpin 0.9s linear infinite;"></div>' +
'<style>@keyframes bootSpin { to { transform: rotate(360deg); } }</style>' +
'<h2 style="margin: 0 0 12px; font-size: 20px;">در حال بازیابی برنامه</h2>' +
'<p style="margin: 0; color: var(--boot-muted); line-height: 2; font-size: 14px;">' +
(text || 'لطفاً چند لحظه صبر کنید.') +
'</p>' +
'</div>' +
'</div>'
}
function renderBootError() {
var app = document.getElementById('app')
if (!app) return
app.innerHTML =
'<div style="min-height: 100vh; display: flex; align-items: center; justify-content: center; direction: rtl; font-family: sans-serif; padding: 24px; background: var(--boot-bg); color: var(--boot-text);">' +
'<div style="width: min(420px, 100%); text-align: center; background: var(--boot-card); border: 1px solid var(--boot-border); border-radius: 24px; padding: 28px 22px;">' +
'<div style="font-size: 42px; margin-bottom: 12px;">⚠️</div>' +
'<h2 style="margin: 0 0 12px; font-size: 20px;">خطا در بارگذاری برنامه</h2>' +
'<p style="margin: 0 0 20px; color: var(--boot-muted); line-height: 2; font-size: 14px;">' +
'ارتباط با سرور برقرار نشد یا فایل‌های برنامه به‌درستی دریافت نشدند.' +
'</p>' +
'<button onclick="window.__APP_BOOT_SIMPLE_RETRY__()" style="padding: 11px 22px; border: 0; border-radius: 12px; background: var(--boot-accent); color: white; cursor: pointer; font-weight: 700;">' +
'تلاش مجدد' +
'</button>' +
'<button onclick="window.__APP_BOOT_CLEAN_RELOAD__()" style="margin-right: 8px; padding: 11px 18px; border: 1px solid var(--boot-border); border-radius: 12px; background: transparent; color: var(--boot-text); cursor: pointer; font-weight: 700;">' +
'پاک‌سازی و تلاش مجدد' +
'</button>' +
'</div>' +
'</div>'
}
async function cleanFetchAndReload() {
renderRecovering('در حال دریافت تنظیمات جدید برنامه...')
var version = await loadRemoteVersion(5)
var freshConfigResult = await fetchFreshConfig(5)
clearReadableCookies()
// clearLocalStorageExceptToken()
await clearServiceWorkersAndCaches()
writeConfigCookie(freshConfigResult.config)
localStorage.setItem(CONFIG_SUCCESS_URL_KEY, freshConfigResult.url)
if (version) {
localStorage.setItem(VERSION_STORAGE_KEY, version)
}
sessionStorage.removeItem(RETRY_KEY)
sessionStorage.removeItem(RECOVERY_KEY)
reloadWithCacheBust()
}
window.__APP_BOOT_SIMPLE_RETRY__ = function () {
sessionStorage.setItem(RETRY_KEY, '1')
reloadWithCacheBust()
}
window.__APP_BOOT_CLEAN_RELOAD__ = async function () {
try {
sessionStorage.setItem(RECOVERY_KEY, '1')
await cleanFetchAndReload()
} catch (error) {
console.error('Manual boot recovery failed:', error)
renderBootError()
}
}
window.__BOOT_TIMEOUT__ = window.setTimeout(async function () {
if (window.__APP_BOOTSTRAPPED__) return
var app = document.getElementById('app')
var stillBooting = app && app.querySelector('.boot-loader')
if (!stillBooting) return
if (!sessionStorage.getItem(RETRY_KEY)) {
renderBootError()
return
}
if (!sessionStorage.getItem(RECOVERY_KEY)) {
sessionStorage.setItem(RECOVERY_KEY, '1')
try {
await cleanFetchAndReload()
} catch (error) {
console.error('Auto boot recovery after retry failed:', error)
renderBootError()
}
return
}
renderBootError()
}, BOOT_TIMEOUT_MS)
})()
</script>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+4479
View File
File diff suppressed because it is too large Load Diff
+40
View File
@@ -0,0 +1,40 @@
{
"name": "landing",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"ant-design-vue": "^3.2.20",
"axios": "^1.6.2",
"lodash": "^4.17.21",
"pinia": "^2.1.4",
"unocss": "^0.55.1",
"unplugin-vue-components": "^0.25.1",
"vue": "^3.3.4",
"vue-router": "^4.2.4"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.3.2",
"@tsconfig/node18": "^18.2.0",
"@types/lodash": "^4.17.7",
"@types/node": "^18.17.0",
"@vitejs/plugin-vue": "^4.2.3",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^11.0.3",
"@vue/tsconfig": "^0.4.0",
"eslint": "^8.45.0",
"eslint-plugin-vue": "^9.15.1",
"less": "^4.2.0",
"prettier": "^3.0.0",
"typescript": "~5.1.6",
"vite": "^4.4.6",
"vue-tsc": "^2.1.10"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

View File
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

+3
View File
@@ -0,0 +1,3 @@
<template>
<router-view />
</template>
+5
View File
@@ -0,0 +1,5 @@
import useAxios from "@/utils/useAxios";
export async function getSettings() {
return await useAxios.get(`api/get_settings`)
}
+11
View File
@@ -0,0 +1,11 @@
import useAxios from "@/utils/useAxios";
import type {Price} from "@/models/home";
export const getChart = async () => await useAxios.get<Array<Array<any>>>(`/api/candle`)
/** @deprecated قیمت up داخل /api/price/last در فیلد up برمی‌گردد */
export const getPrice = async () => await useAxios.get<Price>(`/api/price/up`)
export const getLastPrice = async () => await useAxios.get<Price>(`/api/price/last`)
export const getAllPrices = async () => await useAxios.post('/customer/prices/all')
+14
View File
@@ -0,0 +1,14 @@
import useAxios from "@/utils/useAxios";
import type {PInventory, Product} from "@/models/products";
import type { PWallet, Wallet } from '@/models/wallet'
export const getProducts = async (): Promise<any> => {
return await useAxios.get<Product[]>(`/customer/product/list`)
}
export const getProductInventory = async (): Promise<any> => {
return await useAxios.post<PInventory[]>(`/customer/wallet/product/table`)
}
export const getOneProductWallet = async (id: number): Promise<any> => {
return await useAxios.get<PWallet>(`/customer/wallet/product/${id}`)
}
+110
View File
@@ -0,0 +1,110 @@
@import (less) './var.less';
/**
* Dana Pro (FaNum) — اعداد فارسی
* منبع: DanaPro Webfonts / Farsi numerals
*/
@font-face {
font-family: dana;
font-style: normal;
font-weight: 10;
src: url('../fonts/Dana/woff2/DanaFaNum-Hairline.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-Hairline.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 100;
src: url('../fonts/Dana/woff2/DanaFaNum-Thin.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-Thin.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 200;
src: url('../fonts/Dana/woff2/DanaFaNum-UltraLight.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-UltraLight.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 300;
src: url('../fonts/Dana/woff2/DanaFaNum-Light.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-Light.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 400;
src: url('../fonts/Dana/woff2/DanaFaNum-Regular.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-Regular.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 500;
src: url('../fonts/Dana/woff2/DanaFaNum-Medium.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-Medium.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 600;
src: url('../fonts/Dana/woff2/DanaFaNum-DemiBold.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-DemiBold.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 700;
src: url('../fonts/Dana/woff2/DanaFaNum-Bold.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-Bold.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 800;
src: url('../fonts/Dana/woff2/DanaFaNum-ExtraBold.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-ExtraBold.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 900;
src: url('../fonts/Dana/woff2/DanaFaNum-Black.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-Black.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 930;
src: url('../fonts/Dana/woff2/DanaFaNum-ExtraBlack.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-ExtraBlack.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 960;
src: url('../fonts/Dana/woff2/DanaFaNum-Heavy.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-Heavy.woff') format('woff');
}
@font-face {
font-family: dana;
font-style: normal;
font-weight: 990;
src: url('../fonts/Dana/woff2/DanaFaNum-fat.woff2') format('woff2'),
url('../fonts/Dana/woff/DanaFaNum-fat.woff') format('woff');
}
+13
View File
@@ -0,0 +1,13 @@
@import (less) './var.less';
@import (less) './fonts.less';
@import (less) '../../views/base/aboutUs/desktop/styles/desktop-about-us.less';
@import (less) '../../views/login/desktop/styles/desktop-auth.less';
html {
scroll-behavior: smooth;
}
body {
font-family: var(--App-font-family) !important;
margin: 0;
}
+14
View File
@@ -0,0 +1,14 @@
@prefixCls: 'noname';
@App-primary-color: var(--App-primary-color);
@secondary-color: var(--App-secondary-color);
@prefixCls-font-family: 'dana';
@prefixCls-background-color: var(--App-background-color);
@border-radius-base: 8px;
:root {
--App-primary-color: #0A1B37;
--App-secondary-color: #e0be7f;
--App-background-color: #ffffff;
--App-font-family: 'dana', sans-serif;
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

+5
View File
@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 3.5V14.5" stroke="#1a2b47" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8.25 11L12 14.75L15.75 11" stroke="#1a2b47" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 16.5V18.25C5 19.22 5.78 20 6.75 20H17.25C18.22 20 19 19.22 19 18.25V16.5" stroke="#1a2b47" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 510 B

@@ -0,0 +1,3 @@
<svg width="19" height="10" viewBox="0 0 19 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.5002 0.833496L10.4168 7.91683L6.25016 3.75016L0.833496 9.16683" stroke="#0E9F6E" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Some files were not shown because too many files have changed in this diff Show More