# Component Design — Quran App This document is the mid-level component map for the entire system. Every component, module, and service is described with its responsibilities, interfaces, dependencies, and internal state. Mermaid diagrams show how components relate to each other within each layer and across layers. This document is the reference used by per-flow design documents (e.g. `session-end-flow/design.md`). Per-flow documents go deeper into sequence, error handling, and correctness properties for a specific feature. --- ## 1. System Component Map ```mermaid graph TB subgraph Browser["Browser — React App"] subgraph Providers["Context Providers"] AUTH[AuthContext] LANG[LanguageContext] STU[StudentContext] end subgraph Pages["Page Components"] AUTH_PAGES[Auth Pages] STUDENT_PAGES[Student Pages] SHEIKH_PAGES[Sheikh Pages] ADMIN_PAGES[Admin Pages] SESSION_PAGES[Session Pages] PRACTICE_PAGES[Practice Pages] end subgraph APILayer["API Layer (lib/api/)"] BOOKING_API[bookingApi] STUDENT_API[studentApi] PAYMENT_API[paymentApi] AI_API[aiApi] ADMIN_API[adminApi] SHEIKH_API[sheikhApi] end WEBRTC[useWebRTC hook] end subgraph Backend["Spring Boot Backend"] subgraph Security["Security Layer"] JWT_FILTER[JwtAuthFilter] SEC_CONFIG[SecurityConfig] end subgraph Controllers["Controllers"] AUTH_CTRL[AuthController] STU_CTRL[StudentControllers] SHEIKH_CTRL[SheikhControllers] ADMIN_CTRL[AdminControllers] PAY_CTRL[PaymentController] WS_CTRL[SignalingController] end subgraph Services["Services"] AUTH_SVC[AuthService] STU_SVC[StudentServices] SHEIKH_SVC[SheikhServices] SESSION_SVC[SessionService] PAY_SVC[PaymentServiceStripe] SCHEDULER[TaskScheduler] end subgraph Repos["Repositories"] USER_REPO[UserRepository] SESSION_REPO[SessionRepository] PAY_REPO[PaymentRepository] RECIT_REPO[RecitationRepository] AVAIL_REPO[AvailabilityRepository] REVIEW_REPO[ReviewRepository] end end subgraph External["External Services"] STRIPE[Stripe API] GOOGLE[Google OAuth] AI_SVC[AI Service] GMAIL[Gmail SMTP] DB[(PostgreSQL)] end Pages --> Providers Pages --> APILayer WEBRTC --> Browser APILayer -->|REST HTTP| Controllers WEBRTC -->|WebSocket STOMP| WS_CTRL JWT_FILTER --> Controllers Controllers --> Services Services --> Repos Repos --> DB PAY_SVC --> STRIPE AUTH_SVC --> GOOGLE AUTH_SVC --> GMAIL STU_SVC -->|audio + surah| AI_SVC SCHEDULER --> SESSION_SVC ``` --- ## 2. Frontend Components ### 2.1 Context Providers ```mermaid classDiagram class AuthContext { +user: User | null +loading: boolean +signIn(email, password): Promise~User~ +signInWithGoogle(idToken, role): Promise~User~ +signUp(email, password, ...): Promise~void~ +signOut(): Promise~void~ +updateProfile(updates): void +fetchStreak(): Promise~Streak~ +fetchPracticeStats(): Promise~RecitationStats~ } class LanguageContext { +language: "ar" | "en" +isRTL: boolean +setLanguage(lang): void } class StudentContext { +studentData: StudentData +reload(): void } AuthContext --> LanguageContext : consumed by StudentContext --> AuthContext : depends on ``` **AuthContext** is the most critical context. It: - Stores the authenticated `User` object in React state and `localStorage` - On app load, re-calls `GET /api/auth/verify-profile` to restore + validate session - Exposes all auth operations (signIn, signUp, signOut, Google OAuth) - JWT token is managed here — stored in `localStorage.authToken` **LanguageContext** manages Arabic/English switching and RTL/LTR direction. All page components consume it for translations and layout direction. **StudentContext** caches student-specific dashboard data to avoid re-fetching on every render. --- ### 2.2 Route Guard ```mermaid flowchart TD Request[Route Request] --> Loading{loading?} Loading -->|yes| Spinner[Show Spinner] Loading -->|no| Auth{user exists?} Auth -->|no| SignIn[Redirect /signin] Auth -->|yes| Admin{role = admin?} Admin -->|yes| Render[Render Page] Admin -->|no| Profile{profileCompleted?} Profile -->|no| Complete[Redirect /complete-profile] Profile -->|yes| Render ``` `ProtectedRoute` wraps all authenticated routes. Admin role skips the profile completion check because admin accounts are created manually. --- ### 2.3 Auth Pages ```mermaid graph LR LandingPage -->|sign in| SignIn LandingPage -->|register| Register SignIn -->|forgot| ForgotPasswordRequest ForgotPasswordRequest -->|OTP sent| VerifyOtp VerifyOtp -->|verified| ResetPassword SignIn -->|google| GoogleAuth Register -->|success| CompleteProfile CompleteProfile -->|student| CompleteStudentProfile CompleteProfile -->|sheikh| CompleteSheikhProfile CompleteSheikhProfile -->|submitted| InterviewSchedule ``` | Component | Route | Responsibility | |---|---|---| | `LandingPage` | `/` | Public landing, links to sign in / register | | `SignIn` | `/signin` | Email + password login form | | `Register` | `/register` | Registration form (student or sheikh role) | | `ForgotPasswordRequest` | `/forgot-password` | Email input → triggers OTP email | | `VerifyOtp` | `/verify-otp` | 6-digit OTP entry | | `ResetPassword` | `/reset-password` | New password form | | `GoogleAuth` | `/auth/google` | Handles Google OAuth redirect callback | | `CompleteProfile` | `/complete-profile` | Role selection (student / sheikh) | | `CompleteStudentProfile` | `/complete-profile/student` | Quran level, language, accent wizard | | `CompleteSheikhProfile` | `/complete-profile/sheikh` | Bio, specialization, certificate upload | | `InterviewSchedule` | `/sheikh/interview` | Pending sheikh sees interview date | --- ### 2.4 Dashboard Components ```mermaid graph TB subgraph StudentDashboard STREAK[Streak Widget] STATS[Practice Stats] RECENT_REC[Recent Recitations] UPCOMING_SES[Upcoming Sessions] QUICK_ACTIONS[Quick Actions] end subgraph SheikhDashboard PENDING_REQ[Pending Requests] SHEIKH_STATS[Session Stats] SHEIKH_STUDENTS[Recent Students] RATING_WIDGET[Rating Widget] end subgraph AdminDashboard PLATFORM_STATS[Platform Statistics] USER_OVERVIEW[User Overview] SESSION_OVERVIEW[Session Overview] REVENUE[Revenue Stats] end StudentDashboard --> studentApi SheikhDashboard --> sheikhApi AdminDashboard --> adminApi ``` Each dashboard is a single page component that orchestrates multiple widgets. All data is fetched on mount via parallel `Promise.allSettled` calls — individual widget failures do not crash the dashboard. --- ### 2.5 Session Components This is the most complex area. Components are sequenced along the session lifecycle: ```mermaid graph LR MySessions -->|join button active| WaitingRoom WaitingRoom -->|session time reached| LiveSession LiveSession -->|sheikh ends| MySessions LiveSession -->|student leaves| SessionEndWaiting SessionEndWaiting -->|status = COMPLETED| SessionReport SessionEndWaiting -->|status = MISSED/CANCELLED| MySessions SessionReport -->|submit review| MySessions ``` | Component | Route | Purpose | Key State | |---|---|---|---| | `MySessions` | `/student/sessions` `/sheikh/sessions` | Session list for both roles — tabs for PENDING, UPCOMING, COMPLETED, CANCELLED | `sessions[]`, `focusSession`, `paymentSession` | | `WaitingRoom` | `/waiting-room/:id` | Countdown until session starts, "Enter Session" enabled at T-5min | `session`, `now` (1s interval) | | `LiveSession` | `/session/:id` | Full video call UI — camera/mic controls, chat, sheikh notes, role-specific end/leave buttons | `localStream`, `remoteStream`, `isEndingSession`, `sessionNotes` | | `SessionEndWaiting` | `/session-waiting/:id` | Student waiting screen after leaving — polls status every 5s | `sessionData`, polling interval | | `SessionReport` | `/session-report/:id` | Post-session summary + review form | `sessionData`, `review` | | `SheikhInterviewSession` | `/sheikh/interview-session/:id` | Interview call between admin and pending sheikh | Same as LiveSession | --- ### 2.6 Practice Components ```mermaid sequenceDiagram participant User participant RecordingPractice participant Backend participant AIService User->>RecordingPractice: select surah, record/upload audio RecordingPractice->>Backend: POST /api/student/recitations (multipart) Backend->>AIService: POST /analyze { audio, surah_number } AIService-->>Backend: { overall_stats, ayahs[], user_text } Backend-->>RecordingPractice: RecitationDetailsDto RecordingPractice->>User: show scores + mistake breakdown ``` | Component | Route | Purpose | Key State | |---|---|---|---| | `RecordingPractice` | `/student/practice` | Audio recording (MediaRecorder) or file upload, submit to AI, show results | `audioBlob`, `evaluationResult`, `isProcessing` | | `EvaluationReports` | `/student/evaluations/:id?` | History list of all recitations, detail dialog on click | `recitations[]`, `selected` detail | --- ### 2.7 Sheikh Discovery Components ```mermaid graph TB FindSheikh -->|search + filter| SheikhList[Sheikh Cards] SheikhList -->|click| SheikhProfile SheikhProfile -->|select date| Calendar[Available Dates] Calendar -->|select slot| TimeSlots[Time Slot Chips] TimeSlots -->|book| BookingDialog[Booking Confirmation] BookingDialog -->|confirm| PaymentModal[Stripe Payment Modal] PaymentModal -->|success| MySessions ``` | Component | Route | Purpose | |---|---|---| | `FindSheikh` | `/student/find-sheikh` | Search/filter sheikh list — filter by country, price, rating, language | | `SheikhProfile` | `/student/sheikh/:id` | Full sheikh profile, availability calendar, booking form, reviews | `SheikhProfile` is the most complex student-facing component. It manages: sheikh data fetching, calendar availability loading, time slot selection, booking confirmation dialog, and Stripe payment modal — all in one component. --- ### 2.8 Admin Components ```mermaid graph TB AdminDashboard --> SheikhApproval AdminDashboard --> UserManagement SheikhApproval -->|click sheikh| UserProfileView UserManagement -->|click user| UserProfileView SheikhApproval -->|schedule interview| InterviewSession ``` | Component | Route | Purpose | |---|---|---| | `SheikhApproval` | `/admin/sheikh-approval` | Queue of pending sheikhs — approve, reject, schedule interview | | `UserManagement` | `/admin/users` | All users list with filters — deactivate accounts | | `UserProfileView` | `/admin/user/:id` | Full user detail (student or sheikh) | | `InterviewSession` | `/admin/interview/:id` | Live video call with pending sheikh (same WebRTC infrastructure) | --- ### 2.9 Shared Components ```mermaid graph LR subgraph Navbar Logo --> NavLinks NavLinks --> RoleIndicator RoleIndicator --> LanguageSwitcher LanguageSwitcher --> UserMenu end subgraph ProfilePage BasicInfo[Basic Info Form] PhotoUpload[Profile Photo] PasswordChange[Change Password] end ``` - **`Navbar`** — top navigation. Links change based on role. Shows current language toggle (AR/EN) and user avatar menu. - **`RoleSwitcher`** — dev tool for testing different roles. Not shown in production. - **`ProfilePage`** — shared profile editing for all roles. Route: `/profile`. - **`ErrorBoundary`** — wraps dashboards. Prevents a single widget crash from taking down the full page. - **`ui/`** — 50+ shadcn/Radix UI primitive components (Button, Card, Dialog, etc.). No business logic. --- ### 2.10 API Layer Each file in `lib/api/` is responsible for one domain. All files follow the same pattern: a shared `request()` helper that injects the JWT token, handles 401 token expiry, and normalizes errors. ```mermaid classDiagram class bookingApi { +fetchAvailableDates(sheikhId, from, days) +fetchAvailableSlotsForDay(sheikhId, date) +bookSession(request) +fetchMySessions(status?) +fetchSheikhSessions(status?) +acceptSessionRequest(sessionId) +rejectSessionRequest(sessionId) +fetchSessionReview(sessionId, role) +submitSessionReview(sessionId, review) } class studentApi { +submitRecitationAudio(dto) +fetchRecentRecitations() +fetchRecitationDetail(id) +fetchRecitationStats() +fetchStreak() +fetchPracticeStats() +fetchDashboardData() } class paymentApi { +initiateCardPayment(request) +confirmPaymentWithBackend(paymentIntentId) } class aiApi { +analyzeRecitation(audio, surahNumber) +checkAiHealth() +mapAiResponseToDto(aiResponse) } class adminApi { +fetchPendingSheikhs() +approveSheikh(id) +rejectSheikh(id, reason) +scheduleInterview(id, dateTime) +fetchAllUsers(filters) +deactivateUser(id) } ``` --- ### 2.11 useWebRTC Hook ```mermaid sequenceDiagram participant Component as LiveSession.tsx participant Hook as useWebRTC participant STOMP as STOMP Client participant PC as RTCPeerConnection Component->>Hook: useWebRTC(sessionId, userId) Hook->>STOMP: connect to /ws Hook->>PC: getUserMedia() → localStream STOMP-->>Hook: connected Hook->>STOMP: publish join signal STOMP-->>Hook: receive join from peer Hook->>PC: createOffer() Hook->>STOMP: publish offer STOMP-->>Hook: receive answer Hook->>PC: setRemoteDescription(answer) Note over PC: ICE negotiation PC-->>Hook: remoteStream available Hook-->>Component: { localStream, remoteStream, isConnected, messages } ``` **Exposed interface:** ```typescript { localStream: MediaStream | null remoteStream: MediaStream | null isConnected: boolean connectionQuality: 'good' | 'fair' | 'poor' | 'unknown' messages: ChatMessage[] sendChatMessage(text: string): void toggleVideo(): void toggleAudio(): void } ``` Connection quality is measured every 3 seconds via `RTCPeerConnection.getStats()` on the `candidate-pair` report. RTT < 150ms = good, < 400ms = fair, > 400ms = poor. --- ## 3. Backend Components ### 3.1 Security Layer ```mermaid sequenceDiagram participant Client participant JwtFilter as JwtAuthFilter participant UDS as UserDetailsService participant Chain as SecurityFilterChain participant Controller Client->>JwtFilter: HTTP Request + Bearer token JwtFilter->>JwtFilter: extract JWT from Authorization header JwtFilter->>JwtFilter: jwtService.extractUsername(jwt) JwtFilter->>UDS: loadUserByUsername(email) UDS->>JwtFilter: CustomUserDetails JwtFilter->>JwtFilter: jwtService.isTokenValid(jwt, userDetails) JwtFilter->>Chain: set SecurityContext authentication Chain->>Chain: check role-based access rule Chain->>Controller: forward if authorized Controller-->>Client: response ``` **`JwtAuthenticationFilter`** - Runs on every request (`OncePerRequestFilter`) - Extracts `Bearer` token from `Authorization` header - Validates expiry + signature via `JwtService` - Sets `SecurityContextHolder` so downstream code can call `authentication.getPrincipal()` **`CustomUserDetails`** - Wraps the `User` JPA entity - Exposes `getUserId()` — used by every controller to identify the caller - `isEnabled()` returns `user.status == ALIVE` — deactivated users are rejected at auth time **`SecurityConfig`** - Stateless sessions (`SessionCreationPolicy.STATELESS`) - CORS: allows `http://localhost:*` (must be restricted for production) - Role rules defined as path-prefix matchers (see architecture.md §5 for full table) --- ### 3.2 Auth Module (`dashboard/common`) ```mermaid classDiagram class AuthController { +registerStudent(request) +registerSheikh(request) +login(request) +googleAuth(request) +forgotPassword(request) +verifyOtp(request) +resetPassword(request) +logout() +verifyProfile() +completeGoogleProfile(request) +completeGoogleSheikhProfile(request) } class AuthService { +registerStudent(request): AuthResponse +registerSheikh(request): AuthResponse +login(request): AuthResponse +googleAuth(request): AuthResponse +forgotPassword(request): void +verifyOtp(request): void +resetPasswordWithOtp(request): void +logout(userId): void +verifyProfile(userId): ProfileCheckDto +completeGoogleProfile(email, request): void +completeGoogleSheikhProfile(email, request): void } class JwtService { +generateToken(userDetails): String +extractUsername(token): String +isTokenValid(token, userDetails): boolean +extractExpiration(token): Date } AuthController --> AuthService AuthService --> JwtService AuthService --> UserRepository ``` `AuthService.googleAuth()` calls Google's tokeninfo endpoint to verify the `idToken`, then finds or creates the user. If the user is new, `profileCompleted = false` until they fill the profile wizard. `AuthResponse` is the standard login response: ```java { token: String, // JWT role: String, message: String, user: UserDto, sheikhApprovalStatus: String // only for sheikh role } ``` --- ### 3.3 Student Module (`dashboard/student`) ```mermaid graph TB subgraph Controllers DashCtrl[DashboardController\n/api/student/dashboard] StuCtrl[StudentController\n/api/student/profile] SesCtrl[StudentSessionController\n/api/student/sessions] RecCtrl[StudentRecitationController\n/api/student/recitations] SheikhCtrl[SheikhController\n/api/sheikhs] end subgraph Services DashSvc[DashboardService] StuSessSvc[StudentSessionService] RecitSvc[StudentRecitationService] FindSvc[SheikhServiceFind] StreakSvc[StudentStreakService] end DashCtrl --> DashSvc SesCtrl --> StuSessSvc SesCtrl --> SessionService RecCtrl --> RecitSvc SheikhCtrl --> FindSvc DashSvc --> StreakSvc ``` **`StudentRecitationService`** is the most complex student service: 1. Receives audio `MultipartFile` + `surahNumber` 2. Converts audio to WAV using JAVE2 (ffmpeg wrapper) 3. Calls external AI service via `RestTemplate` with `multipart/form-data` 4. Parses AI JSON response into `AIReport` DTO 5. Calculates `wordScore`, `tashkeelScore`, `totalScore` from the AI report 6. Saves `Recitation` entity with `mistakesReportJson` (full AI response as JSONB) **`StudentSessionService`** handles booking: - Validates `startDateTime` is in the future - Calls `SheikhAvailabilityService.validateSessionSlot()` — checks slot is within availability and not already booked by REQUESTED/TOPAY/SCHEDULED sessions - Creates `Session` with status = `REQUESTED` --- ### 3.4 Sheikh Module (`dashboard/sheikh`) ```mermaid graph TB subgraph Controllers SesCtrl2[SessionController\n/api/sheikh/sessions] AvailCtrl[AvailabilityController\n/api/sheikh/availability] StudCtrl[MyStudents\n/api/sheikh/students] DashCtrl2[sheikhMainDashboard\n/api/sheikh/dashboard] PendCtrl[pendingSheikhController\n/api/sheikh/profile] ReviewCtrl[NotesAndReviewsController\n/api/reviews] end subgraph Services SessionSvc[SessionService] AvailSvc[SheikhAvailabilityService] StudSvc[MyStudentsServiceImpl] DashSvc2[sheikhDashboardService] ReviewSvc[NotesAndReviewsService] end SesCtrl2 --> SessionSvc AvailCtrl --> AvailSvc StudCtrl --> StudSvc DashCtrl2 --> DashSvc2 ReviewCtrl --> ReviewSvc ``` **`SessionService`** is the central service for session lifecycle. It owns all status transitions and event-driven scheduling: ```mermaid classDiagram class SessionService { -taskScheduler: TaskScheduler +rescheduleExistingSessionsOnStartup() +updateSessionStatus(sheikhId, sessionId, newStatus) +recordJoin(userId, sessionId) +recordLeave(userId, sessionId) +startSession(userId, sessionId) +endSession(sheikhId, sessionId, notes) -scheduleMissedCheck(sessionId, scheduledStart) -scheduleSheikhNoShowCheck(sessionId, scheduledStart) -scheduleCancelIfUnpaid(sessionId, scheduledStart) +checkAndMarkMissed(sessionId) +checkAndMarkMissedBySheikhNoShow(sessionId) +cancelIfUnpaid(sessionId) +triggerRefundForMissedSession(sessionId) +convertToDto(session): SessionDTO } ``` Three event-driven scheduled tasks fire automatically: - `scheduleMissedCheck` — fires at `scheduledStart + 1 min`. If neither party joined → `MISSED` + refund - `scheduleSheikhNoShowCheck` — fires at `scheduledStart + 10 min`. If sheikh didn't join → `MISSED` + refund - `scheduleCancelIfUnpaid` — fires at `scheduledStart - 5 min`. If still `TOPAY` → `CANCELLED` All three are registered on startup (`@EventListener(ApplicationReadyEvent)`) for surviving sessions. **`SheikhAvailabilityService`** manages the weekly recurring availability template: - `setAvailability()` — replaces overlapping slots with new ones - `getSlotsForDate()` — generates 1-hour slots within the availability window, minus already-booked sessions - `validateSessionSlot()` — called at booking time to reject out-of-window or overlapping requests --- ### 3.5 Admin Module (`dashboard/admin`) ```mermaid graph TB subgraph Controllers AdminCtrl[AdminController\n/api/admin/users] DashCtrl3[AdminMainDashboard\n/api/admin/dashboard] ApproveCtrl[ShiekhManagementAPProval\n/api/admin/sheikh-approvals] UserMgmtCtrl[UserManagement] end subgraph Services AdminSvc[AdminService] DashSvc3[AdminDashboardService] ApproveSvc[PendingSheikhService] end AdminCtrl --> AdminSvc DashCtrl3 --> DashSvc3 ApproveCtrl --> ApproveSvc ``` Admin module is relatively thin — it reads across all domain repositories to produce statistics and management views. Approval flow: `PENDING → INTERVIEW_SCHEDULED → APPROVED/REJECTED`. --- ### 3.6 Payment Module (`payment`) ```mermaid classDiagram class PaymentControllerStripe { +initiateCard(request): StripePaymentResponse +confirmPayment(paymentIntentId): StripePaymentResponse +confirmSession(sessionId): void +payoutSheikh(sessionId): StripeRefundResponse +refundStudent(sessionId, reason): StripeRefundResponse +createSheikhAccount(sheikhId): Map } class PaymentServiceStripe { -commissionPct: 15% +initiateCardPayment(request): StripePaymentResponse +confirmPayment(paymentIntentId): StripePaymentResponse +onSheikhAcceptsSession(sessionId): void +payoutSheikh(sessionId): StripeRefundResponse +refundStudent(sessionId, reason): StripeRefundResponse +createSheikhConnectedAccount(sheikhId): Map -savePayment(...): Payment -calcCommission(amount): BigDecimal } PaymentControllerStripe --> PaymentServiceStripe PaymentServiceStripe --> PaymentRepository PaymentServiceStripe --> SessionRepository PaymentServiceStripe --> UserRepository ``` Payment status lifecycle: ```mermaid stateDiagram-v2 [*] --> PENDING: initiateCardPayment PENDING --> PAID: confirmPayment (Stripe succeeded) PENDING --> FAILED: confirmPayment (Stripe failed) PAID --> PAYOUT_DONE: payoutSheikh PAID --> REFUNDED: refundStudent FAILED --> PENDING: retry (old record deleted) REFUNDED --> [*] PAYOUT_DONE --> [*] ``` If a `PENDING` payment record already exists when `initiateCardPayment` is called again, the existing Stripe PaymentIntent is retrieved and returned rather than creating a duplicate. --- ### 3.7 WebSocket / Signaling Module (`websocket`) ```mermaid classDiagram class WebSocketConfig { +configureMessageBroker(registry) +registerStompEndpoints(registry) } class SignalingController { -messagingTemplate: SimpMessagingTemplate +handleSignal(message: SignalingMessage): void } class SignalingMessage { +type: String +sender: String +sessionId: String +data: Object } WebSocketConfig --> SignalingController SignalingController --> SignalingMessage ``` `SignalingController` has a single handler: `@MessageMapping("/signal")`. It receives any signaling message and broadcasts it to `/topic/session/{sessionId}`. All session participants (student + sheikh) are subscribed to this topic. The controller does not interpret the message content — that is handled entirely by the browser's WebRTC stack. --- ### 3.8 Data Entities ```mermaid erDiagram USER ||--o| STUDENT_PROFILE : has USER ||--o| SHEIKH_PROFILE : has USER ||--o| STREAK : has USER ||--o{ AVAILABILITY : sets USER ||--o{ SESSION : "books as student" USER ||--o{ SESSION : "teaches as sheikh" USER ||--o{ RECITATION : records USER ||--o{ PAYMENT : "pays as student" USER ||--o{ PAYMENT : "receives as sheikh" USER ||--o{ REVIEW : writes SESSION ||--o| PAYMENT : has SESSION ||--o| REVIEW : has USER { bigint id PK varchar email UK varchar passwordHash varchar fullName enum role enum status varchar authProvider timestamp createdAt } SESSION { bigint id PK timestamp scheduledStart timestamp scheduledEnd timestamp actualStart timestamp actualEnd timestamp studentJoinedAt timestamp sheikhJoinedAt enum status decimal price } PAYMENT { bigint id PK decimal amount enum paymentStatus varchar transactionId UK decimal platformCommission decimal sheikhPayout } RECITATION { bigint id PK varchar surahName decimal wordScore decimal tashkeelScore jsonb mistakesReportJson } ``` --- ## 4. External Services ### 4.1 AI Recitation Service ```mermaid graph LR Backend -->|POST /analyze\nmultipart: audio + surah_number| AIService[AI Service\nngrok URL] Backend -->|GET /\nhealth check| AIService AIService -->|JSON: surah_info, overall_stats, ayahs| Backend ``` - Hosted externally, exposed via ngrok tunnel - Requires `ngrok-skip-browser-warning: true` header - Returns per-ayah word-stage and tashkeel-stage analysis - Scores are 0–100 percentages (not 0–1 fractions) - Backend stores full response as JSONB in `recitations.mistakes_report_json` ### 4.2 Stripe ```mermaid graph LR Backend -->|Create PaymentIntent| Stripe Frontend -->|confirmCardPayment with clientSecret| Stripe Backend -->|Retrieve PaymentIntent| Stripe Backend -->|Create Transfer to connected account| Stripe Backend -->|Create Refund| Stripe Backend -->|Create Express Account| Stripe ``` Two Stripe products are used: - **Payment Intents** — for student card payments - **Stripe Connect** (Custom accounts) — for sheikh payouts. Sheikhs get a Stripe connected account with a test bank attached. ### 4.3 Google OAuth ```mermaid graph LR Frontend -->|Google Identity Services button| Google Google -->|idToken| Frontend Frontend -->|POST /api/auth/google { idToken, role }| Backend Backend -->|verify idToken| GoogleAPIClient[Google API Client] GoogleAPIClient -->|{ email, name, picture }| Backend ``` Google OAuth is used for social login. The backend verifies the `idToken` using the `google-api-client` library. If the email doesn't exist in the DB, a new user is created and directed to the profile completion wizard. ### 4.4 Gmail SMTP Used exclusively for OTP password reset emails. Configured with: - Host: `smtp.gmail.com` - Port: `587` (STARTTLS) - Authentication: Gmail app password (not the account password) --- ## 5. Component Dependency Summary ```mermaid graph TD subgraph Frontend FE_AUTH[Auth Pages] --> FE_API[API Layer] FE_SESSIONS[Session Pages] --> FE_API FE_PRACTICE[Practice Pages] --> FE_API FE_ADMIN[Admin Pages] --> FE_API FE_SESSIONS --> WEBRTC_HOOK[useWebRTC] FE_API --> AUTH_CTX[AuthContext] end subgraph Backend BE_CTRL[Controllers] --> BE_SVC[Services] BE_SVC --> BE_REPO[Repositories] BE_SVC --> BE_SCHEDULER[TaskScheduler] BE_CTRL --> SEC[Security Layer] end FE_API -->|REST| BE_CTRL WEBRTC_HOOK -->|WebSocket| BE_CTRL BE_SVC -->|JDBC| DB[(PostgreSQL)] BE_SVC --> STRIPE[Stripe] BE_SVC --> AI[AI Service] BE_SVC --> GMAIL[Gmail SMTP] SEC --> GOOGLE[Google OAuth] ``` --- ## 6. Flow Index The following per-flow design documents go deeper into each major feature using the components defined above: | Flow | Document | Components Involved | |---|---|---| | Session End Flow | `.kiro/specs/session-end-flow/design.md` | `LiveSession`, `SessionEndWaiting`, `SessionService`, `PaymentServiceStripe` | | Authentication Flow | _next_ | `SignIn`, `Register`, `GoogleAuth`, `AuthContext`, `AuthService`, `JwtService` | | Session Booking Flow | _next_ | `SheikhProfile`, `MySessions`, `bookingApi`, `StudentSessionService`, `SheikhAvailabilityService` | | Payment Flow | _next_ | `MySessions`, `PaymentModal`, `paymentApi`, `PaymentServiceStripe`, Stripe | | AI Practice Flow | _next_ | `RecordingPractice`, `EvaluationReports`, `aiApi`, `StudentRecitationService`, AI Service | | Sheikh Approval Flow | _next_ | `SheikhApproval`, `InterviewSession`, `AdminService`, `SessionService` (WebRTC) | | WebRTC Session Flow | _next_ | `LiveSession`, `WaitingRoom`, `useWebRTC`, `SignalingController`, `SessionService` |