Remove user-app v1 and ship pending order, auth, and app fixes.

Drop the duplicate customer app from the monorepo and keep user-app-v2 as the only app; include order pricing, admin cart, OTP/SMS, and dashboard cache updates.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
mahmood
2026-10-28 16:22:32 +03:30
co-authored by Cursor
parent bc881a0a8a
commit 520454481b
367 changed files with 335 additions and 28536 deletions
+68 -1
View File
@@ -132,6 +132,35 @@
</div>
</a-tab-pane>
<!-- دکمه سفارشی — یک دکمه با عنوان و لینک، قابل فعال/غیرفعال -->
<a-tab-pane key="custom-button" tab="دکمه سفارشی">
<a-form layout="vertical" class="custom-btn-form" @submit.prevent="saveCustomButton">
<a-form-item label="وضعیت">
<a-switch
v-model:checked="customButton.enabled"
checked-children="فعال"
un-checked-children="غیرفعال"
/>
</a-form-item>
<a-form-item label="عنوان دکمه">
<a-input
v-model:value="customButton.title"
placeholder="مثلاً پشتیبانی تلگرام"
style="max-width: 360px"
/>
</a-form-item>
<a-form-item label="لینک">
<a-input
v-model:value="customButton.link"
placeholder="https://..."
style="max-width: 360px"
dir="ltr"
/>
</a-form-item>
<a-button type="primary" @click="saveCustomButton">ذخیره دکمه</a-button>
</a-form>
</a-tab-pane>
<!-- سینی‌ها — super admin only -->
<a-tab-pane v-if="users.isSuperAdmin" key="collections" tab="سینی ها">
<div class="row">
@@ -218,6 +247,9 @@ const tagsInputValue = ref('');
// ── mobile slider (legacy key: mobile_main_slider)
const sliders = ref<{ image: string; link: string }[]>([]);
// ── custom button (Setting key: custom_button)
const customButton = ref({ enabled: false, title: '', link: '' });
// ── collections
const collections = ref<{ id: string; title: string }[]>([]);
const newCollection = ref('');
@@ -315,6 +347,27 @@ async function saveSliders() {
}
}
async function saveCustomButton() {
const title = customButton.value.title.trim();
const link = customButton.value.link.trim();
if (customButton.value.enabled && (!title || !link)) {
message.warning('برای فعال‌سازی، عنوان و لینک را وارد کنید');
return;
}
try {
await api.put('const/custom_button', {
val: {
enabled: customButton.value.enabled,
title,
link,
},
});
message.success('دکمه سفارشی ذخیره شد');
} catch (e: any) {
message.error(e?.response?.data?.message ?? 'خطا در ذخیره');
}
}
// ── collections
async function loadCollections() {
const { data } = await api.post('ciny', { page: 1, limit: 200 });
@@ -363,9 +416,20 @@ onMounted(async () => {
try {
loading.value = true;
await Promise.all([loadBrands(), users.isSuperAdmin ? loadCollections() : Promise.resolve()]);
const [t, s] = await Promise.all([api.get('const/__list__tags'), api.get('const/slider')]);
const [t, s, btn] = await Promise.all([
api.get('const/__list__tags'),
api.get('const/slider'),
api.get('const/custom_button'),
]);
tags.value = Array.isArray(t.data) ? t.data : [];
sliders.value = Array.isArray(s.data) ? s.data : [];
if (btn.data && typeof btn.data === 'object' && !Array.isArray(btn.data)) {
customButton.value = {
enabled: Boolean(btn.data.enabled),
title: String(btn.data.title ?? ''),
link: String(btn.data.link ?? ''),
};
}
} catch (e) {
console.log(e);
} finally {
@@ -446,6 +510,9 @@ onMounted(async () => {
.mt-4 {
margin-top: 1rem;
}
.custom-btn-form {
max-width: 480px;
}
@media (max-width: 575px) {
/* the add-row input fills what the button leaves instead of a fixed 260px */