diff --git a/docs/user-guide-notion.txt b/docs/user-guide-notion.txt new file mode 100644 index 0000000..9a20141 --- /dev/null +++ b/docs/user-guide-notion.txt @@ -0,0 +1,180 @@ +راهنمای کاربری منتایم +======================== + +این فایل برای کپی مستقیم در Notion، Google Docs یا Microsoft Word آماده شده است. +سرفصل‌ها را با Heading 1 / Heading 2 قالب‌بندی کنید. + +------------------------------------------------------------ + +منتایم چیست؟ + +منتایم پلتفرمی برای کشف کسب‌وکارهای محلی و رزرو آنلاین نوبت است (کارواش، آرایشگاه و خدمات مشابه). + +نقش مشتری: پیدا کردن کسب‌وکار، رزرو، پرداخت، امتیاز +نقش صاحب کسب‌وکار: مدیریت خدمات، ساعات، رزروها و صفحه کسب‌وکار + +------------------------------------------------------------ + +۱) شروع کار و ورود + +ورود با کد یکبارمصرف (پیشنهادی) +• منو → ورود +• حالت «کد یکبارمصرف» را انتخاب کنید +• شماره موبایل را وارد کنید (مثال: 09121234567) +• دریافت کد تأیید +• کد ۴ رقمی پیامک‌شده را وارد کنید + +ورود با رمز عبور +• حالت «رمز عبور» را انتخاب کنید +• موبایل و رمز را وارد کنید → ورود + +نکته: اولین بار با کد یکبارمصرف وارد شوید و بعداً از پروفایل رمز بسازید. +می‌توانید با «ادامه بدون ورود» فقط مرور کنید؛ برای رزرو باید وارد شوید. + +------------------------------------------------------------ + +۲) کشف کسب‌وکارها + +• از «خانه» لیست کسب‌وکارها را ببینید +• در صورت نیاز جستجو یا فیلتر دسته را استفاده کنید +• روی کارت بزنید تا صفحه کسب‌وکار باز شود + +روی کارت معمولاً می‌بینید: تصویر کاور، نام، امتیاز، زیرعنوان، دسته، آدرس + +------------------------------------------------------------ + +۳) صفحه کسب‌وکار و رزرو + +در صفحه کسب‌وکار: +• نام، توضیحات، گالری، نکات برجسته، تخفیف (در صورت فعال بودن)، خدمات +• دکمه «رزرو نوبت» + +مراحل رزرو: +1. کلاس خدمات (فقط اگر کلاس‌بندی فعال باشد) +2. انتخاب خدمات +3. تاریخ و ساعت +4. اطلاعات و یادداشت اختیاری +5. تایید نهایی → ثبت نهایی رزرو + +بعد از ثبت: +• اگر تأیید خودکار فعال باشد → آماده پرداخت آنلاین +• اگر تأیید دستی باشد → در انتظار تأیید صاحب کسب‌وکار + +------------------------------------------------------------ + +۴) پرداخت + +• مسیر: رزروها → پرداخت (یا لینک پرداخت) +• مبلغ و جزئیات را بررسی کنید +• پرداخت آنلاین را انجام دهید +• تخفیف درصدی معمولاً خودکار اعمال می‌شود +• اگر نوبت رایگان باشگاه مشتریان باشد، مبلغ رایگان نشان داده می‌شود + +------------------------------------------------------------ + +۵) رزروهای مشتری + +از منو «رزروها»: +• در انتظار تأیید +• منتظر پرداخت → دکمه پرداخت +• تأیید شده +• انجام شده +• لغو شده → امکان لغو در وضعیت‌های مجاز + +اگر خالی باشد: «هنوز رزروی ثبت نکردید.» + +------------------------------------------------------------ + +۶) امتیاز و حسن انجام کار + +بعد از «انجام شد» توسط صاحب کسب‌وکار: +1. امتیاز ۱ تا ۵ ستاره +2. اگر حسن انجام کار فعال باشد: تمایل ندارم / تمایل دارم (+ مبلغ) +3. در غیر این صورت فقط ثبت امتیاز + +------------------------------------------------------------ + +۷) پروفایل + +• موبایل و نقش +• تنظیم / تغییر رمز عبور +• مشتری: ثبت کسب‌وکار من +• صاحب: ورود به پنل کسب‌وکار +• خروج از حساب + +------------------------------------------------------------ + +۸) ثبت کسب‌وکار + +• وارد شوید و «ثبت کسب‌وکار» را بزنید +• نام، دسته، توضیحات، آدرس، تلفن را پر کنید +• ارسال درخواست +• پس از تأیید ادمین، پنل صاحب کسب‌وکار فعال می‌شود + +------------------------------------------------------------ + +۹) پنل صاحب کسب‌وکار (کسب‌وکار من) + +اطلاعات: نام، زیرعنوان، توضیحات، تلفن، آدرس، نکات برجسته لندینگ (حداکثر ۳ مورد) + +لوگو و تصاویر: لوگوی روشن/تاریک + گالری و کاور + +تنظیمات نوبت‌دهی: +• پذیرش همزمان +• گام نوبت‌دهی (دقیقه) +• تأیید خودکار درخواست‌ها +• حسن انجام کار +• تخفیف درصدی (عنوان، درصد، کد نمایشی، اولین رزرو یا همه رزروها) + +ساعات پذیرش آنلاین: بازه‌های قابل رزرو در روزهای هفته + +خدمات: +• افزودن خدمت و قیمت/مدت +• خدمت رایگان دوره‌ای (اختیاری) +• کلاس‌بندی خدمات (اختیاری) +• خدمت سفارشی → پس از تأیید ادمین + +------------------------------------------------------------ + +۱۰) رزروهای صاحب کسب‌وکار + +تب‌ها: در انتظار تأیید | تأیید شده | لغو شده + +اقدامات: +• تأیید +• انجام شد (باعث باز شدن امتیاز برای مشتری می‌شود) +• لغو (با علت لغو) + +نکته: صاحب کسب‌وکار کسب‌وکار خودش را در لیست کشف نمی‌بیند و برای خودش رزرو نمی‌کند. + +------------------------------------------------------------ + +۱۱) منوی پایین موبایل + +خانه | رزروها | ثبت کسب‌وکار یا کسب‌وکار من | ورود یا خروج + +------------------------------------------------------------ + +۱۲) سؤالات متداول + +س: بدون ورود می‌توانم رزرو کنم؟ +ج: خیر. مرور آزاد است؛ رزرو نیاز به ورود دارد. + +س: کد تخفیف را کجا وارد کنم؟ +ج: معمولاً لازم نیست؛ تخفیف فعال خودکار اعمال می‌شود. + +س: چرا کسب‌وکار خودم را در لیست نمی‌بینم؟ +ج: عمدی است. از «کسب‌وکار من» مدیریت کنید. + +س: خدمت سفارشی کی دیده می‌شود؟ +ج: بعد از تأیید ادمین. + +س: چطور رمز بسازم؟ +ج: ورود با OTP → پروفایل → تنظیم رمز عبور. + +------------------------------------------------------------ + +نسخه آنلاین داخل اپ: /guide +نسخه Markdown: docs/user-guide.md + +منتایم — رزرو آنلاین خدمات محلی diff --git a/docs/user-guide.md b/docs/user-guide.md new file mode 100644 index 0000000..e64834a --- /dev/null +++ b/docs/user-guide.md @@ -0,0 +1,284 @@ +# راهنمای کاربری منتایم + +راهنمای کامل استفاده از پلتفرم رزرو آنلاین خدمات محلی **منتایم** برای مشتریان و صاحبان کسب‌وکار. + +> این فایل نسخه Markdown است. نسخه آنلاین در مسیر `/guide` و نسخه مناسب کپی در Notion/Docs در فایل `user-guide-notion.txt` قرار دارد. + +--- + +## فهرست مطالب + +1. [منتایم چیست؟](#۱-منتایم-چیست) +2. [شروع کار و ورود](#۲-شروع-کار-و-ورود) +3. [کشف کسب‌وکارها](#۳-کشف-کسب‌وکارها) +4. [صفحه کسب‌وکار و رزرو نوبت](#۴-صفحه-کسب‌وکار-و-رزرو-نوبت) +5. [پرداخت](#۵-پرداخت) +6. [مدیریت رزروها (مشتری)](#۶-مدیریت-رزروها-مشتری) +7. [امتیازدهی و حسن انجام کار](#۷-امتیازدهی-و-حسن-انجام-کار) +8. [پروفایل کاربری](#۸-پروفایل-کاربری) +9. [ثبت کسب‌وکار](#۹-ثبت-کسب‌وکار) +10. [پنل صاحب کسب‌وکار](#۱۰-پنل-صاحب-کسب‌وکار) +11. [مدیریت رزروها (صاحب کسب‌وکار)](#۱۱-مدیریت-رزروها-صاحب-کسب‌وکار) +12. [منوی پایین موبایل](#۱۲-منوی-پایین-موبایل) +13. [سؤالات متداول](#۱۳-سؤالات-متداول) + +--- + +## ۱. منتایم چیست؟ + +منتایم پلتفرمی برای **کشف کسب‌وکارهای محلی** و **رزرو آنلاین نوبت** است؛ مثلاً کارواش، آرایشگاه و خدمات مشابه. + +| نقش | کار اصلی | +|-----|----------| +| **مشتری** | پیدا کردن کسب‌وکار، رزرو، پرداخت، امتیاز | +| **صاحب کسب‌وکار** | مدیریت خدمات، ساعات، رزروها و تنظیمات لندینگ | + +--- + +## ۲. شروع کار و ورود + +### ورود با کد یکبارمصرف (پیشنهادی) + +1. از منو **ورود** را بزنید (یا مسیر `/login`). +2. حالت **کد یکبارمصرف** را انتخاب کنید. +3. **شماره موبایل** خود را وارد کنید (مثال: `09121234567`). +4. **دریافت کد تأیید** را بزنید. +5. در صفحه **کد تأیید**، کد ۴ رقمی پیامک‌شده را وارد کنید. + +### ورود با رمز عبور + +1. در صفحه ورود، حالت **رمز عبور** را انتخاب کنید. +2. موبایل و رمز را وارد کنید و **ورود** را بزنید. + +> **نکته:** اگر اولین بار است، با کد یکبارمصرف وارد شوید و بعداً از پروفایل رمز بسازید. + +### ادامه بدون ورود + +می‌توانید با **ادامه بدون ورود** کسب‌وکارها را ببینید؛ برای ثبت رزرو باید وارد شوید. + +--- + +## ۳. کشف کسب‌وکارها + +از **خانه** (`/app`): + +1. لیست کسب‌وکارهای فعال را ببینید. +2. در صورت نیاز، با جستجو یا فیلتر **دسته** محدود کنید. +3. روی کارت کسب‌وکار بزنید تا صفحه آن باز شود. + +### ظاهر کارت‌ها + +| عرض صفحه | چیدمان | +|----------|--------| +| کمتر از ۴۲۵px | لیست افقی | +| ۴۲۵px به بالا | کارت با تصویر کاور (۲ تا ۵ ستون بسته به عرض) | + +روی کارت معمولاً می‌بینید: تصویر کاور، نام، امتیاز، زیرعنوان، دسته و آدرس. + +--- + +## ۴. صفحه کسب‌وکار و رزرو نوبت + +### صفحه لندینگ + +در صفحه کسب‌وکار می‌توانید ببینید: + +- نام، زیرعنوان و توضیحات +- گالری تصاویر +- نکات برجسته (مثلاً رضایت مشتریان، رزرو آنلاین آسان) +- بنر تخفیف (در صورت فعال بودن) +- لیست خدمات + +دکمه اصلی: **رزرو نوبت** + +> اگر کسب‌وکار غیرفعال باشد پیام **این کسب‌وکار فعلاً غیرفعال است.** نمایش داده می‌شود. + +### مراحل رزرو (`/app/businesses/:id/book`) + +بسته به تنظیمات کسب‌وکار، مراحل ممکن است شامل این‌ها باشد: + +1. **کلاس خدمات** (فقط اگر کلاس‌بندی فعال باشد؛ مثلاً اندازه خودرو) +2. **انتخاب خدمات** (می‌توانید چند خدمت انتخاب کنید؛ دوباره زدن = لغو انتخاب) +3. **تاریخ و ساعت** +4. **اطلاعات و پرداخت** — یادداشت اختیاری +5. **تایید نهایی** → **ثبت نهایی رزرو** + +اگر بین راه وارد نباشید، به ورود هدایت می‌شوید و بعد به همین مسیر برمی‌گردید. + +### بعد از ثبت رزرو + +| حالت کسب‌وکار | نتیجه | +|---------------|--------| +| **تأیید خودکار** فعال | رزرو تأیید می‌شود و آماده **پرداخت آنلاین** است | +| تأیید دستی | وضعیت **در انتظار تأیید**؛ پس از تأیید صاحب، لینک پرداخت می‌آید | + +--- + +## ۵. پرداخت + +مسیر: `/app/bookings/pay` + +1. مبلغ، کسب‌وکار و تاریخ را بررسی کنید. +2. **پرداخت آنلاین** را بزنید. +3. پس از موفقیت به لیست رزروها برگردید. + +اگر خدمت با باشگاه مشتریان **رایگان** شده باشد، مبلغ رایگان نمایش داده می‌شود. + +تخفیف درصدی (در صورت فعال بودن) معمولاً **خودکار** اعمال می‌شود و نیازی به وارد کردن کد نیست. + +--- + +## ۶. مدیریت رزروها (مشتری) + +از منو **رزروها** (`/app/bookings`): + +| وضعیت | معنی تقریبی | +|--------|-------------| +| در انتظار تأیید | منتظر تأیید صاحب کسب‌وکار | +| منتظر پرداخت | باید پرداخت کنید | +| تأیید شده | پرداخت شده / تأیید نهایی | +| انجام شده | خدمت انجام شده | +| لغو شده | لغو شده | + +**اقدامات مشتری:** + +- **پرداخت** (وقتی منتظر پرداخت است) +- **لغو** (در وضعیت‌های مجاز) + +اگر رزروی نباشد: **هنوز رزروی ثبت نکردید.** + +--- + +## ۷. امتیازدهی و حسن انجام کار + +بعد از اینکه صاحب کسب‌وکار رزرو را **انجام شد** علامت بزند: + +1. پنجره **امتیاز** (۱ تا ۵ ستاره) باز می‌شود. +2. اگر **حسن انجام کار** فعال باشد: + - **تمایل ندارم** → فقط امتیاز ثبت می‌شود + - **تمایل دارم** → مبلغ قدردانی را وارد و پرداخت می‌کنید +3. اگر حسن انجام کار غیرفعال باشد، فقط **ثبت امتیاز** دارید. + +--- + +## ۸. پروفایل کاربری + +از آیکون پروفایل در هدر: + +- مشاهده موبایل و نقش +- **تنظیم / تغییر رمز عبور** +- مشتری‌ها: لینک **ثبت کسب‌وکار من** +- صاحبان: **ورود به پنل کسب‌وکار** +- **خروج از حساب** + +--- + +## ۹. ثبت کسب‌وکار + +مسیر: `/app/register-business` (باید مشتری باشید و وارد شده باشید) + +1. **نام کسب‌وکار**، **دسته‌بندی**، توضیحات، آدرس و تلفن را پر کنید. +2. **ارسال درخواست** را بزنید. +3. پس از بررسی ادمین، در صورت تأیید، نقش شما به صاحب کسب‌وکار تبدیل می‌شود و پنل فعال می‌شود. + +> اگر از قبل کسب‌وکار داشته باشید یا درخواست در انتظار بررسی داشته باشید، امکان ارسال مجدد نیست. + +--- + +## ۱۰. پنل صاحب کسب‌وکار + +مسیر: `/app/owner` — عنوان منو: **کسب‌وکار من** + +### اطلاعات کسب‌وکار + +نام، زیرعنوان، توضیحات، تلفن، آدرس و **نکات برجسته لندینگ** (حداکثر ۳ مورد از لیست عمومی). + +### لوگو و تصاویر + +- لوگوی **حالت روشن** و **حالت تاریک** (اختیاری؛ اگر یکی باشد برای هر دو استفاده می‌شود) +- گالری تصاویر + انتخاب **کاور** + +### تنظیمات نوبت‌دهی + +- **پذیرش همزمان** +- **گام نوبت‌دهی (دقیقه)** +- **تأیید خودکار درخواست‌ها** +- **حسن انجام کار** +- **تخفیف درصدی** (عنوان، درصد، کد نمایشی، فقط اولین رزرو یا همه رزروها) + +### ساعات پذیرش آنلاین + +تعیین بازه‌های قابل رزرو برای روزهای هفته (همه روزها یکسان یا جداگانه). + +### خدمات و قیمت‌ها + +- افزودن خدمت از قالب‌ها یا پیشنهاد **خدمت سفارشی** (نیاز به تأیید ادمین) +- قیمت و مدت +- اختیاری: **خدمت رایگان دوره‌ای** (هر N بار یک‌بار رایگان) +- اختیاری: **کلاس‌بندی خدمات** + +--- + +## ۱۱. مدیریت رزروها (صاحب کسب‌وکار) + +در **رزروها** تب‌ها: + +- **در انتظار تأیید** +- **تأیید شده** +- **لغو شده** + +اقدامات: + +| دکمه | کار | +|------|-----| +| **تأیید** | تأیید درخواست مشتری | +| **انجام شد** | پایان خدمت (امتیاز برای مشتری باز می‌شود) | +| **لغو** | لغو با وارد کردن **علت لغو** | + +> صاحب کسب‌وکار کسب‌وکار خودش را در لیست کشف نمی‌بیند و نمی‌تواند برای خودش رزرو کند. + +--- + +## ۱۲. منوی پایین موبایل + +| آیتم | چه زمانی | +|------|----------| +| **خانه** | همیشه | +| **رزروها** | همیشه (بدون ورود → صفحه ورود) | +| **ثبت کسب‌وکار** | اگر صاحب کسب‌وکار نباشید | +| **کسب‌وکار من** | اگر صاحب کسب‌وکار باشید | +| **ورود** | مهمان | +| **خروج** | وارد شده | + +--- + +## ۱۳. سؤالات متداول + +**آیا بدون ورود می‌توانم رزرو کنم؟** +خیر. مرور آزاد است؛ ثبت رزرو نیاز به ورود دارد. + +**کد تخفیف را کجا وارد کنم؟** +معمولاً نیاز نیست؛ اگر تخفیف فعال باشد هنگام رزرو/پرداخت خودکار اعمال می‌شود. + +**چرا کسب‌وکار خودم را در لیست نمی‌بینم؟** +عمدی است تا صاحب کسب‌وکار برای خودش رزرو نکند. از **کسب‌وکار من** مدیریت کنید. + +**خدمت سفارشی کی در لیست مشتری می‌آید؟** +پس از تأیید ادمین در پنل مدیریت پلتفرم. + +**چطور رمز بسازم؟** +با OTP وارد شوید → پروفایل → تنظیم رمز عبور. + +--- + +## نسخه آنلاین و کپی + +| خروجی | مسیر | +|--------|------| +| صفحه وب داخل اپ | `/guide` | +| این فایل Markdown | `docs/user-guide.md` | +| متن ساخت‌یافته برای Notion/Docs | `docs/user-guide-notion.txt` | + +--- + +*منتایم — رزرو آنلاین خدمات محلی* diff --git a/public/landing/hero-car-wash.jpg b/public/landing/hero-car-wash.jpg deleted file mode 100644 index 331f800..0000000 --- a/public/landing/hero-car-wash.jpg +++ /dev/null @@ -1 +0,0 @@ -404 \ No newline at end of file diff --git a/src/components/auth/DesktopLoginHeroPanel.vue b/src/components/auth/DesktopLoginHeroPanel.vue index 341ee16..3eff68d 100644 --- a/src/components/auth/DesktopLoginHeroPanel.vue +++ b/src/components/auth/DesktopLoginHeroPanel.vue @@ -122,7 +122,7 @@ const features: { label: string; description: string[]; icon: AppIconName }[] = function onImageError() { if (fallbackUsed.value) return; fallbackUsed.value = true; - heroSrc.value = '/landing/hero-car-wash.jpg'; + heroSrc.value = '/landing/hero-reference.png'; } diff --git a/src/components/profile/ProfilePanel.vue b/src/components/profile/ProfilePanel.vue index a3491c3..beb6a3a 100644 --- a/src/components/profile/ProfilePanel.vue +++ b/src/components/profile/ProfilePanel.vue @@ -24,6 +24,15 @@ + + راهنمای کاربری + مشاهده + +
import { computed, ref } from 'vue'; -import { useRouter } from 'vue-router'; +import { RouterLink, useRouter } from 'vue-router'; import { setPassword } from '@/api/auth'; import { ApiError } from '@/api/client'; import AppButton from '@/components/ui/AppButton.vue'; diff --git a/src/layouts/MobileLoginLayout.vue b/src/layouts/MobileLoginLayout.vue index 353a4b6..56b0fd6 100644 --- a/src/layouts/MobileLoginLayout.vue +++ b/src/layouts/MobileLoginLayout.vue @@ -89,7 +89,7 @@ watch(loginHeroSrc, (src) => { function onImageError() { if (fallbackUsed.value) return; fallbackUsed.value = true; - heroSrc.value = '/landing/hero-car-wash.jpg'; + heroSrc.value = '/landing/hero-reference.png'; } onMounted(() => { diff --git a/src/router/index.ts b/src/router/index.ts index 0d62599..f678c3c 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -68,6 +68,11 @@ const router = createRouter({ component: () => import('@/views/app/AppOwnerView.vue'), meta: { requiresAuth: true, requiresBusinessOwner: true }, }, + { + path: '/guide', + name: 'user-guide', + component: () => import('@/views/guide/UserGuideView.vue'), + }, { path: '/home', redirect: '/app' }, ], }); diff --git a/src/stores/platform-settings.ts b/src/stores/platform-settings.ts index 9c6d806..b841ef0 100644 --- a/src/stores/platform-settings.ts +++ b/src/stores/platform-settings.ts @@ -1,64 +1,64 @@ -import { defineStore } from 'pinia'; -import { computed, ref } from 'vue'; -import { fetchPlatformSettings } from '@/api/platform-settings'; -import { - DEFAULT_LOGO_DARK, - DEFAULT_LOGO_LIGHT, - resolveLogoPair, - uploadUrl, -} from '@/utils/media'; - -const DEFAULT_LOGIN_HERO = '/landing/hero-car-wash.jpg'; - -export const usePlatformSettingsStore = defineStore('platformSettings', () => { - const loginHeroImageUrl = ref(null); - const logoLightUrl = ref(null); - const logoDarkUrl = ref(null); - const loaded = ref(false); - const loading = ref(false); - - const defaultLogoLight = DEFAULT_LOGO_LIGHT; - const defaultLogoDark = DEFAULT_LOGO_DARK; - - const loginHeroSrc = computed( - () => uploadUrl(loginHeroImageUrl.value) || DEFAULT_LOGIN_HERO, - ); - - const logoSources = computed(() => - resolveLogoPair(logoLightUrl.value, logoDarkUrl.value), - ); - - async function load(force = false) { - if (loaded.value && !force) return; - if (loading.value) return; - - loading.value = true; - try { - const data = await fetchPlatformSettings(); - loginHeroImageUrl.value = data.loginHeroImageUrl; - logoLightUrl.value = data.logoLightUrl; - logoDarkUrl.value = data.logoDarkUrl; - loaded.value = true; - } catch { - loginHeroImageUrl.value = null; - logoLightUrl.value = null; - logoDarkUrl.value = null; - loaded.value = true; - } finally { - loading.value = false; - } - } - - return { - loginHeroImageUrl, - logoLightUrl, - logoDarkUrl, - defaultLogoLight, - defaultLogoDark, - loginHeroSrc, - logoSources, - loaded, - loading, - load, - }; -}); +import { defineStore } from 'pinia'; +import { computed, ref } from 'vue'; +import { fetchPlatformSettings } from '@/api/platform-settings'; +import { + DEFAULT_LOGO_DARK, + DEFAULT_LOGO_LIGHT, + resolveLogoPair, + uploadUrl, +} from '@/utils/media'; + +const DEFAULT_LOGIN_HERO = '/landing/hero-reference.png'; + +export const usePlatformSettingsStore = defineStore('platformSettings', () => { + const loginHeroImageUrl = ref(null); + const logoLightUrl = ref(null); + const logoDarkUrl = ref(null); + const loaded = ref(false); + const loading = ref(false); + + const defaultLogoLight = DEFAULT_LOGO_LIGHT; + const defaultLogoDark = DEFAULT_LOGO_DARK; + + const loginHeroSrc = computed( + () => uploadUrl(loginHeroImageUrl.value) || DEFAULT_LOGIN_HERO, + ); + + const logoSources = computed(() => + resolveLogoPair(logoLightUrl.value, logoDarkUrl.value), + ); + + async function load(force = false) { + if (loaded.value && !force) return; + if (loading.value) return; + + loading.value = true; + try { + const data = await fetchPlatformSettings(); + loginHeroImageUrl.value = data.loginHeroImageUrl; + logoLightUrl.value = data.logoLightUrl; + logoDarkUrl.value = data.logoDarkUrl; + loaded.value = true; + } catch { + loginHeroImageUrl.value = null; + logoLightUrl.value = null; + logoDarkUrl.value = null; + loaded.value = true; + } finally { + loading.value = false; + } + } + + return { + loginHeroImageUrl, + logoLightUrl, + logoDarkUrl, + defaultLogoLight, + defaultLogoDark, + loginHeroSrc, + logoSources, + loaded, + loading, + load, + }; +}); diff --git a/src/views/guide/UserGuideView.vue b/src/views/guide/UserGuideView.vue new file mode 100644 index 0000000..1c50844 --- /dev/null +++ b/src/views/guide/UserGuideView.vue @@ -0,0 +1,472 @@ + + +