diff --git a/docs/cattell_glasser_api_guide.md b/docs/cattell_glasser_api_guide.md new file mode 100644 index 0000000..d894ded --- /dev/null +++ b/docs/cattell_glasser_api_guide.md @@ -0,0 +1,309 @@ +# راهنمای جامع API و هوک‌های فرانت‌اند برای آزمون‌های کتل و گلاسر (Cattell & Glasser API Guide) + +این مستند شامل ساختار اندپوئینت‌های بک‌اند، مدل داده‌ها و نحوه استفاده از هوک‌های ایجاد شده در فرانت‌اند برای آزمون **شخصیت‌شناسی کتل (16PF)** و **۵ نیاز اساسی گلاسر (Glasser)** می‌باشد. + +--- + +## 📌 اندپوئینت‌های بک‌اند (Backend Endpoints) + +تمامی درخواست‌ها نیازمند احراز هویت (`Authorization: Token `) هستند و توسط کلاینت HTTP پروژه به صورت خودکار ارسال می‌شوند. + +| ردیف | آزمون | نوع | آدرس اندپوئینت | پارامتر اختیاری | 설명 / کاربرد | +|---|---|---|---|---|---| +| ۱ | کتل (Cattell) | GET | `/api/marriage/cattell/questions/` | `lang=fa` | دریافت لیست کامل سوالات کتل | +| ۲ | کتل (Cattell) | POST | `/api/marriage/cattell/submit/` | - | ثبت پاسخ‌های آزمون کتل | +| ۳ | کتل (Cattell) | GET | `/api/marriage/cattell/result/` | `lang=fa` | دریافت تحلیل و نتیجه آزمون کتل | +| ۴ | گلاسر (Glasser) | GET | `/api/marriage/glasser/questions/` | `lang=fa` | دریافت لیست کامل سوالات ۵ نیاز گلاسر | +| ۵ | گلاسر (Glasser) | POST | `/api/marriage/glasser/submit/` | - | ثبت پاسخ‌های آزمون گلاسر | +| ۶ | گلاسر (Glasser) | GET | `/api/marriage/glasser/result/` | `lang=fa` | دریافت تحلیل و نتیجه آزمون گلاسر | + +> **نکته:** پارامتر `lang` یا `language_code` می‌تواند یکی از کد زبان‌های پشتیبانی شده باشد (مانند `fa`, `en`, `ar`, `tr`, `de`, `fr`, ...). + +--- + +## 📑 ساختار خروجی و ورودی داده‌ها (Data Schemas) + +### ۱. آزمون کتل (Cattell 16PF) + +#### 🔹 دریافت سوالات (`GET /api/marriage/cattell/questions/?lang=fa`) +**پاسخ موفق (HTTP 200 OK):** +```json +{ + "questions": [ + { + "question_number": 1, + "text": "من حاضرم به هر سوال تا حد امکان صادقانه پاسخ دهم", + "item_type": "standard", + "options": [ + "بله", + "به اندازه کافی واضح نیست", + "نه" + ] + }, + { + "question_number": 2, + "text": "ترجیح میدم خونه داشته باشم", + "item_type": "standard", + "options": [ + "بله", + "من نمی دانم", + "نه" + ] + } + ] +} +``` + +#### 🔹 ارسال پاسخ‌ها (`POST /api/marriage/cattell/submit/`) +**بدنه درخواست (Request Body):** +> ⚠️ **تذکر مهم:** تمام سوالات آزمون باید به صورت یک‌باره و کامل ارسال شوند. گزینه انتخاب شده معمولاً `A` یا `B` یا `C` یا متن گزینه می‌باشد. + +```json +{ + "responses": [ + { + "question_number": 1, + "option": "A" + }, + { + "question_number": 2, + "option": "B" + } + ] +} +``` + +**پاسخ موفق (HTTP 201 Created):** +```json +{ + "detail": "آزمون با موفقیت ثبت شد." +} +``` + +#### 🔹 دریافت نتیجه (`GET /api/marriage/cattell/result/?lang=fa`) +**پاسخ موفق (HTTP 200 OK):** +```json +{ + "results": { + "A": { + "name": "گرمی و صمیمیت (Warmth)", + "score": 6.5 + }, + "B": { + "name": "استدلال و تفکر انتزاعی (Reasoning)", + "score": 8.0 + } + } +} +``` + +--- + +### ۲. آزمون ۵ نیاز گلاسر (Glasser 5 Needs) + +#### 🔹 دریافت سوالات (`GET /api/marriage/glasser/questions/?lang=fa`) +**پاسخ موفق (HTTP 200 OK):** +```json +{ + "questions": [ + { + "question_number": 1, + "text": "مسایلی مثل پس انداز، مخارج زندگی، مسکن، آینده شغلی و.. تا چه اندازه ذهن شما را به خود مشغول می دارد؟", + "factor": "بقا (امنیت و نیازهای زیستی)", + "factor_code": "S" + }, + { + "question_number": 2, + "text": "تا چه اندازه به سلامت جسمانی، بهداشت و احتمال ابتلا به بیماری فکر میکنید؟", + "factor": "بقا (امنیت و نیازهای زیستی)", + "factor_code": "S" + } + ] +} +``` + +#### 🔹 ارسال پاسخ‌ها (`POST /api/marriage/glasser/submit/`) +**بدنه درخواست (Request Body):** +> ⚠️ **تذکر مهم:** نمره هر سوال متغیری بین ۱ تا ۵ می‌باشد و تمام سوالات آزمون گلاسر باید به صورت یک‌جا ارسال شوند. + +```json +{ + "responses": [ + { + "question_number": 1, + "score": 4 + }, + { + "question_number": 2, + "score": 5 + } + ] +} +``` + +**پاسخ موفق (HTTP 201 Created):** +```json +{ + "detail": "آزمون با موفقیت ثبت شد.", + "results": { + "S": { + "factor_name": "بقا (امنیت و نیازهای زیستی)", + "score": 24, + "percentage": 80.0 + } + } +} +``` + +--- + +## 🛠️ روش استفاده در فرانت‌اند (React Query Hooks) + +هوک‌های سفارشی بر پایه TanStack Query مطابق استاندارد کل پروژه در مسیرهای زیر پیاده‌سازی شده‌اند: +- `@/hooks/marriage/use-cattell` +- `@/hooks/marriage/use-glasser` + +### نمونه ۱: دریافت و نمایش سوالات آزمون کتل (Cattell) + +```tsx +"use client"; + +import { useCattellQuestionsQuery } from "@/hooks/marriage/use-cattell"; + +export default function CattellTestComponent() { + const { data, isLoading, isError, error } = useCattellQuestionsQuery("fa"); + + if (isLoading) { + return
در حال دریافت سوالات کتل...
; + } + + if (isError) { + return
خطا در دریافت سوالات: {String(error)}
; + } + + return ( +
+

تعداد سوالات کتل: {data?.questions.length}

+ +
+ ); +} +``` + +--- + +### نمونه ۲: دریافت سوالات و ثبت پاسخ‌های آزمون گلاسر (Glasser) + +```tsx +"use client"; + +import { useState } from "react"; +import { + useGlasserQuestionsQuery, + useSubmitGlasserAssessmentMutation, +} from "@/hooks/marriage/use-glasser"; + +export default function GlasserTestComponent() { + const { data: questionsData, isLoading } = useGlasserQuestionsQuery("fa"); + const submitMutation = useSubmitGlasserAssessmentMutation(); + + const [scores, setScores] = useState>({}); + + const handleScoreChange = (qNum: number, score: number) => { + setScores((prev) => ({ ...prev, [qNum]: score })); + }; + + const handleSubmit = () => { + if (!questionsData) return; + + const payload = { + responses: Object.entries(scores).map(([qNum, score]) => ({ + question_number: Number(qNum), + score, + })), + }; + + submitMutation.mutate(payload, { + onSuccess: (res) => { + alert("آزمون گلاسر با موفقیت ثبت شد!"); + console.log("نتایج:", res.results); + }, + onError: (err) => { + alert("خطا در ثبت آزمون گلاسر"); + }, + }); + }; + + if (isLoading) return
در حال دریافت سوالات گلاسر...
; + + return ( +
+

آزمون ۵ نیاز گلاسر

+ {questionsData?.questions.map((q) => ( +
+

{q.question_number}. {q.text} ({q.factor})

+
+ {[1, 2, 3, 4, 5].map((val) => ( + + ))} +
+
+ ))} + + +
+ ); +} +``` + +--- + +### نمونه ۳: دریافت نتایج آزمون + +```tsx +"use client"; + +import { useCattellResultQuery } from "@/hooks/marriage/use-cattell"; +import { useGlasserResultQuery } from "@/hooks/marriage/use-glasser"; + +export default function TestResultsComponent() { + const { data: cattellResults } = useCattellResultQuery("fa"); + const { data: glasserResults } = useGlasserResultQuery("fa"); + + return ( +
+

نتایج کتل

+
{JSON.stringify(cattellResults, null, 2)}
+ +

نتایج گلاسر

+
{JSON.stringify(glasserResults, null, 2)}
+
+ ); +} +``` diff --git a/public/assets/images/test-intro-hero.png b/public/assets/images/test-intro-hero.png new file mode 100644 index 0000000..6f7f48f Binary files /dev/null and b/public/assets/images/test-intro-hero.png differ diff --git a/src/app/[lang]/questions-list/[slug]/page.tsx b/src/app/[lang]/questions-list/[slug]/page.tsx index 2a365d6..334af5f 100644 --- a/src/app/[lang]/questions-list/[slug]/page.tsx +++ b/src/app/[lang]/questions-list/[slug]/page.tsx @@ -1,4 +1,14 @@ -export { - default, - generateStaticParams, -} from "@/app/questions-list/[slug]/page"; +import { getQuestionListItems } from "@/data/question-data"; +import { locales } from "@/i18n/config"; +import QuestionDetailPage from "@/app/questions-list/[slug]/page"; + +export function generateStaticParams() { + return locales.flatMap((lang) => + getQuestionListItems(lang).map((item) => ({ + lang, + slug: item.slug, + })), + ); +} + +export default QuestionDetailPage; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6b7b0ea..884583d 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -44,6 +44,7 @@ export default function RootLayout({