Ristek Tutor Kelas Frontend - Documentation
| Document Status | ||
|---|---|---|
| Document Owner | Product Engineering 2026 | Product Engineering 2026 |
| Contributors | ||
| Project Links | https://github.com/RistekCSUI/ristek-tutor-frontend | https://github.com/RistekCSUI/ristek-tutor-frontend |
| Project Links | https://classtutor.ristek.cs.ui.ac.id | https://classtutor.ristek.cs.ui.ac.id |
| Project Links | Backend provides Swagger UI at /api/schema/swagger-ui/ | Backend provides Swagger UI at /api/schema/swagger-ui/ |
| Team | Theodore Kevin Himawan | theodore.kevin@ristek.cs.ui.ac.id |
| Team | Ari Darrell Muljono | darrell@ristek.cs.ui.ac.id |
| Team | Grace Karina | gracekarin@ristek.cs.ui.ac.id |
| Team | Yeshua Marco G. Manurung | marco@ristek.cs.ui.ac.id |
π Background
Overviewβ
The Ristek Tutor Kelas Frontend is the web application for the RISTEK peer tutoring platform. It provides UI students with an interface to find and book tutoring sessions, manage schedules, and track session logs. Tutors can create availability slots, manage their sessions, and submit post-session logs with proof for admin verification. The application integrates with UI SSO for authentication and supports role-based navigation for tutees and tutors.
Stakeholdersβ
- Users: UI students (tutees seeking tutoring), student tutors, admin (log verification via backend)
- Upstream Dependencies: Ristek Tutor Kelas Backend API, UI SSO CAS (https://sso.ui.ac.id/cas2), MinIO/S3 (file storage for images)
- Downstream Consumers: None (this is the end-user client application)
Scope & Boundariesβ
- In Scope: Landing page, SSO authentication flow, user profile management with onboarding, tutor registration with course scores, session browsing and booking (with payment proof upload), session management (tutor and tutee views), session rescheduling, schedule creation (tutor), session log creation and detail view, role-based navigation, responsive design.
- Out of Scope: Backend API logic, admin panel for log verification/payment, payment gateway integration, email notifications.
βοΈ Architecture & Design
System Diagramβ
Architecture Decisions (ADRs)β
- Language/Framework: TypeScript 5 / Next.js 15 (App Router) / React 19
- Build: Turbopack in development (next dev --turbopack)
- State Management: React Context (AuthContext) + local useState; no global state library
- Styling: Tailwind CSS 4 with tw-animate-css, class-variance-authority for component variants, tailwind-merge + clsx for class composition
- UI Primitives: Radix UI (accordion, dialog, dropdown, popover, checkbox, scroll area, separator) + RSuite (rich components)
- Form Handling: react-hook-form 7 + Zod 4 for schema validation
- Data Tables: TanStack React Table 8 with custom pagination and filters
- HTTP Client: Axios 1.10 with 401 interceptor for automatic token refresh
- Icons: Lucide React + React Icons
- Toast Notifications: Sonner
- Date Handling: date-fns + react-day-picker
- Fonts: Geist, Geist Mono, Poppins (via next/font/google)
- Deployment: Vercel via GitHub Actions
- Rendering: force-dynamic root layout with server-side user fetching; server actions for data mutations
π»Technical Specifications
API Documentationβ
The frontend uses a dual-layer API approach: Next.js API Routes (app/api/) β BFF proxy for authentication, handling cookie management (httpOnly JWT tokens) Server Actions (actions/) β Direct backend calls with auth headers for data operations Backend base URL: NEXT_PUBLIC_API_URL environment variable. Axios configuration (config/axiosConfig.ts): Base URL from NEXT_PUBLIC_API_URL withCredentials: true for cookie-based auth 401 response interceptor: attempts token refresh via /api/auth/refresh, retries request; on failure redirects to /login
Next.js API Routes (BFF Proxy)β
| Endpoint | Method | Backend Target | Description |
|---|---|---|---|
/api/auth/login | POST | SSO redirect | Initiates SSO login, returns CAS login URL |
/api/auth/callback | POST | POST /user/sso/callback/ | Validates CAS ticket, sets JWT cookies |
/api/auth/login-dev | POST | POST /user/login/ | Dev login with username/password, sets JWT cookies |
/api/auth/refresh | POST | POST /user/token/refresh/ | Refresh JWT, updates cookies |
/api/auth/me | GET | GET /user/me/ | Get current user from access token cookie |
/api/auth/logout | POST | β | Clears JWT cookies |
/api/tutor/upgrade | POST | POST /user/apply/ | Submit tutor application |
Server Actions (actions/)β
| Action | Backend Target | Description |
|---|---|---|
| getUserAction | GET /user/me/ | Fetch current user profile (server-side) |
| getTutorsAction | GET /user/tutors | List all tutors |
| submitProfileForm | PATCH /user/update_profile/ | Update user profile (onboarding) |
| submitApplyTutorAction | POST /user/apply/ | Submit tutor application with course scores |
| registerTutorAction | POST /user/apply/ | Register as tutor |
| getMatkulAction | GET /tutor-session/matkul/ | List mata kuliah |
| getAvailableSessions | GET /tutor-session/sessions/ | Browse available sessions (filterable) |
| createTutorSession | POST /tutor-session/tutor/sessions/ | Create tutor session |
| getMySessionsAction | GET /tutor-session/... | List own sessions |
| getSessionDetailAction | GET /tutor-session/... | Session detail |
| getTutorSessionsAction | GET /tutor-session/tutor/sessions/ | List tutor sessions |
| getTuteeSessionsAction | GET /tutor-session/tutee/sessions/ | List tutee sessions |
| getTuteeSession | GET /tutor-session/tutee/sessions/{id}/ | Tutee session detail |
| submitPesanSesiForm | POST /tutor-session/tutee/book/{id}/ | Book a session |
| updateSessionStatusAction | PUT /tutor-session/... | Update session status |
| updateSessionEmailsAction | PATCH /tutor-session/tutee/sessions/{id}/emails/ | Update booking emails |
| updateTuteeSessionAction | PUT /tutor-session/tutee/sessions/{id}/ | Update tutee session |
| upgradeBookingAction | PUT /tutor-session/tutee/sessions/{id}/ | Upgrade session package |
| rescheduleSessionAction | POST /tutor-session/tutee/reschedule/... | Reschedule session |
| getRescheduleSessionData | GET /tutor-session/... | Get reschedule data |
| getTutorLogs | GET /logs/tutor/logs | List tutor logs |
| getTutorLogDetail | GET /logs/tutor/logs/{id} | Log detail |
| createLogSesi | POST /logs/tutor/logs | Create session log |
Pages & Routesβ
| Route | File | Auth | Description |
|---|---|---|---|
/ | app/page.tsx | Public | Landing page (hero, info sections, FAQ) |
/login | app/login/page.tsx | Public | SSO UI login page |
/profil | app/profil/page.tsx | Protected | User profile (view & edit, onboarding) |
/profil/register-tutor | app/profil/register-tutor/page.tsx | Protected | Tutor registration form (course scores, GPA) |
/pesan-sesi | app/pesan-sesi/page.tsx | Protected | Browse and book tutoring sessions (multi-step) |
/pesan-sesi/berhasil | app/pesan-sesi/berhasil/page.tsx | Protected | Booking success confirmation |
/sesi-saya | app/sesi-saya/page.tsx | Protected | My sessions (tutor/tutee table view) |
/sesi-saya/[id] | app/sesi-saya/[id]/page.tsx | Protected | Session detail (status, links, actions) |
/sesi-saya/[id]/upgrade | app/sesi-saya/[id]/upgrade/page.tsx | Protected | Upgrade session package type |
/tambah-jadwal | app/tambah-jadwal/page.tsx | Protected | Add schedule/availability (tutor only) |
/log-sesi | app/log-sesi/page.tsx | Protected | Tutor session logs list |
/log-sesi/tambah | app/log-sesi/tambah/page.tsx | Protected | Create new session log |
/log-sesi/[id] | app/log-sesi/[id]/page.tsx | Protected | Log detail view |
Authentication Flowβ
- SSO Login: user clicks login β frontend redirects to
https://sso.ui.ac.id/cas2/login?service=<APP_URL>/loginβ CAS authenticates β redirects back with?ticket=parameter. - Ticket Processing:
SSOHandlerdetects?ticket=in the URL β callsPOST /api/auth/callbackwith ticket and service URL β API route validates ticket with backendPOST /user/sso/callback/β backend returns JWT tokens β API route setsaccess_token(7-day) andrefresh_token(30-day) as httpOnly cookies. - Session Restoration: on page load,
root layout.tsxcallsgetUserAction()server-side to fetch the current user β passes it asinitialUsertoAuthWrappercontext. - Token Refresh: Axios 401 interceptor calls
POST /api/auth/refreshβ API route readsrefresh_tokencookie β sends it to backend β updatesaccess_tokencookie β retries the failed request. - Logout: calls
POST /api/auth/logoutβ clears cookies β sends hidden iframe to SSO logout URL (https://sso.ui.ac.id/cas2/logout) for SSO session cleanup β redirects to/. - Dev Login:
POST /api/auth/login-devwith username/password for development and testing. - Middleware (
middleware.ts): checksaccess_tokencookie on all non-public routes. Public routes are/and/login. Unauthenticated requests are redirected to/login?redirect=<originalPath>.
Data Model/Schemaβ
| File | Key Types |
|---|---|
| types/user.ts | UserType (npm, username, email, full_name, is_tutor, application_status, tutor_profile, jurusan, batch, preferred_subjects, is_complete, profile_picture_url), TutorProfile, Subject, ApplicationStatus, ClassTypeEnum |
| types/session.ts | SessionStatus (tersedia, telah dipesan, dikonfirmasi, direschedule, in request reschedule, dibatalkan, etc.), TutorSession, sessionPackage (triad/penta/hepta/deca), SessionTableData, SessionOption |
| types/log.ts | LogStatus, MataKuliah, TutorSessionInfo, TutorLog, LogTableData |
| types/matkul.ts | Matkul, MatkulOption |
| types/navbar.ts | UserRole, NavLinkType, BaseNavLink, IconNavLink, StringNavLink |
| Zod schemas (form validation): | |
| modules/PesanSesi/schema.ts β pesanSesiSchema (date range, email list, package selection) | |
| modules/TambahLogSesi/types/schema.ts β logSesiSchema (log creation validation) |
Project Structureβ
ristek-tutor-frontend/
βββ .github/
β βββ workflows/
β βββ deploy.yml # Production: push to main β Vercel prod
β βββ staging.yml # Staging: push to staging β Vercel preview
βββ actions/ # Server actions (backend API calls)
β βββ getUserAction.ts # Fetch current user
β βββ getTutorsAction.ts # List tutors
β βββ submitProfileForm.ts # Update profile (onboarding)
β βββ submitApplyTutorAction.ts # Apply as tutor
β βββ getMatkulAction.ts # List mata kuliah
β βββ getAvailableSessions.ts # Browse sessions
β βββ createTutorSession.ts # Create session (tutor)
β βββ getMySessionsAction.ts # My sessions
β βββ getSessionDetailAction.ts # Session detail
β βββ getTutorSessionsAction.ts # Tutor sessions
β βββ getTuteeSessionsAction.ts # Tutee sessions
β βββ getTuteeSession.ts # Tutee session detail
β βββ submitPesanSesiForm.ts # Book session
β βββ updateSessionStatusAction.ts # Update session status
β βββ updateSessionEmailsAction.ts # Update booking emails
β βββ updateTuteeSessionAction.ts # Update tutee session
β βββ upgradeBookingAction.ts # Upgrade session package
β βββ rescheduleSessionAction.ts # Reschedule session
β βββ getRescheduleSessionData.ts # Reschedule data
β βββ getTutorLogs.ts # List tutor logs
β βββ getTutorLogDetail.ts # Log detail
β βββ createLogSesi.ts # Create session log
β βββ registerTutorAction.ts # Register tutor
βββ app/
β βββ api/
β β βββ auth/
β β β βββ callback/route.ts # SSO CAS ticket validation
β β β βββ login/route.ts # SSO login redirect
β β β βββ login-dev/route.ts # Dev login (username/password)
β β β βββ logout/route.ts # Clear JWT cookies
β β β βββ me/route.ts # Current user proxy
β β β βββ refresh/route.ts # JWT refresh proxy
β β βββ tutor/
β β βββ upgrade/route.ts # Tutor application proxy
β βββ layout.tsx # Root layout (AuthWrapper, Navbar, Footer, Toaster)
β βββ globals.css # Global styles (Tailwind, design tokens)
β βββ page.tsx # Landing page
β βββ login/page.tsx # Login page
β βββ profil/ # Profile pages
β β βββ layout.tsx # Profile layout
β β βββ page.tsx # Profile view/edit
β β βββ register-tutor/page.tsx # Tutor registration
β βββ pesan-sesi/ # Session booking
β β βββ page.tsx # Browse & book sessions
β β βββ berhasil/page.tsx # Booking success
β βββ sesi-saya/ # My sessions
β β βββ page.tsx # Sessions table
β β βββ [id]/
β β βββ page.tsx # Session detail
β β βββ upgrade/page.tsx # Upgrade package
β βββ tambah-jadwal/page.tsx # Add schedule (tutor)
β βββ log-sesi/ # Session logs
β βββ page.tsx # Logs list
β βββ tambah/page.tsx # Create log
β βββ [id]/page.tsx # Log detail
βββ components/
β βββ auth/
β β βββ SSOHandler.tsx # Detects ?ticket= and triggers SSO callback
β βββ elements/
β β βββ Layout/
β β β βββ Navbar.tsx # Top nav with role-based links
β β β βββ Footer.tsx # Site footer
β β β βββ NavLink.tsx # Nav link component
β β β βββ ProfileDropdown.tsx # Profile menu with logout
β β βββ form/
β β β βββ RistekCalendar.tsx # Calendar date picker
β β β βββ RistekCalendarModal.tsx # Calendar in modal
β β β βββ RistekCombobox.tsx # Searchable combobox
β β β βββ RistekDropdownFilter.tsx # Dropdown filter
β β β βββ RistekFileInput.tsx # File upload input
β β β βββ RistekInput.tsx # Text input
β β β βββ RistekMultiSelect.tsx # Multi-select
β β β βββ RistekTimeInput.tsx # Time picker
β β βββ table/
β β β βββ DataTable.tsx # Generic data table
β β β βββ FilterBar.tsx # Table filter bar
β β β βββ Pagination.tsx # Pagination controls
β β β βββ TablePagination.tsx # Table pagination variant
β β β βββ ActionButtons.tsx # Row action buttons
β β βββ AccordionFAQ.tsx # FAQ accordion
β β βββ FAQCard.tsx # FAQ card
β β βββ InfoContainer.tsx # Info section container
β β βββ LogStatusCard.tsx # Log status display
β β βββ ProfileCard.tsx # User profile card
β β βββ RistekBreadcrumb.tsx # Breadcrumb navigation
β β βββ RistekCheckbox.tsx # Checkbox
β β βββ RistekToast.tsx # Toast notification wrapper (Sonner)
β β βββ SessionStatusCard.tsx # Session status display
β β βββ StatusBadge.tsx # Status badge (colored)
β β βββ Typography.tsx # Typography variants
β βββ ui/ # Radix-based primitives (shadcn/ui pattern)
β β βββ accordion.tsx, badge.tsx, breadcrumb.tsx, button.tsx
β β βββ calendar.tsx, checkbox.tsx, combobox.tsx, command.tsx
β β βββ dialog.tsx, dropdown-menu.tsx, multi-select.tsx
β β βββ popover.tsx, scroll-area.tsx, separator.tsx
β β βββ sonner.tsx, table.tsx
β βββ ErrorList.tsx # Error list display
βββ config/
β βββ axiosConfig.ts # Axios instance with 401 refresh interceptor
βββ context/
β βββ AuthContext.tsx # Auth state, SSO callback handler, logout
βββ hooks/
β βββ useFileUpload.ts # File upload hook
β βββ useMediaQuery.ts # Responsive media query hook
βββ lib/
β βββ utils.ts # cn() class merge utility
β βββ roleUtils.ts # Role-based redirect helpers
β βββ sessionUtils.ts # Session status/type helpers
β βββ tableUtils.ts # Table formatting utilities
βββ modules/ # Feature modules (page-level components)
β βββ LandingPage/ # Landing: hero, info sections, FAQ
β βββ Login/ # Login page module
β βββ Profil/ # Profile: view, edit, tutor registration
β βββ PesanSesi/ # Book session: multi-step (browse β details)
β βββ SesiSaya/ # My sessions: table, detail, reschedule, upgrade
β βββ TambahJadwal/ # Add schedule form (tutor)
β βββ LogSesi/ # Log list with data table
β βββ TambahLogSesi/ # Create log form with Zod schema
βββ types/ # Shared TypeScript types
β βββ user.ts, session.ts, log.ts, matkul.ts, navbar.ts
βββ public/
β βββ images/ # Static images (landing, profile, navbar, footer)
β βββ icons/ # SVG icons
βββ middleware.ts # Route protection (access_token cookie check)
βββ next.config.ts # Next.js config (10mb body limit, image domains)
βββ tsconfig.json # TypeScript config (strict, @/* alias)
βββ postcss.config.mjs # PostCSS (Tailwind)
βββ eslint.config.mjs # ESLint config
βββ package.json # Dependencies and scripts
Componentsβ
| Layer | Paths | Responsibility |
|---|---|---|
| Root Layout | app/layout.tsx | Server-side async layout that fetches the current user via getUserAction() and provides it as initialUser to AuthWrapper. Wraps all pages with Navbar, Footer, SSOHandler, and Toaster (Sonner). Uses force-dynamic rendering. Loads Geist, Geist Mono, and Poppins fonts. |
| SSOHandler | components/auth/SSOHandler.tsx | Client component that monitors the URL for ?ticket= query parameters on mount. When detected, triggers handleSSOCallback() from AuthContext to complete the SSO login flow. Handles the CAS redirect-back automatically. |
| Navbar | components/elements/Layout/Navbar.tsx | Role-aware navigation bar. Shows different links for tutors (Sesi Saya, Tambah Jadwal, Log Sesi) vs tutees (Pesan Sesi, Sesi Saya). Includes mobile hamburger menu and ProfileDropdown with avatar and logout. |
| Profile Module | modules/Profil/ | Profile view and edit form with onboarding support. Includes ProfileForm for personal details (name, phone, LINE ID, preferred subjects, class type), DaftarTutor section for tutor registration, DaftarUlang for re-registration, and VerifiedCard for verified status display. |
| Register Tutor | modules/Profil/RegisterTutor/ | Tutor registration form with RegisterTutorForm section for submitting course scores and GPA. |
| Pesan Sesi Module | modules/PesanSesi/ | Multi-step session booking flow. Step 1: browse available sessions with filters (mata kuliah, tutor, date). Step 2: fill booking details (package type, participant emails, payment proof upload). Uses Zod schema validation. SessionCard and SessionSelect components for session selection UI. |
| Sesi Saya Module | modules/SesiSaya/ | Session management with TanStack Table (SesiSayaTable), column definitions (tableSchema), RescheduleModal for rescheduling flow, and UpgradePaket for upgrading session package types. |
| Tambah Jadwal Module | modules/TambahJadwal/ | Tutor schedule creation form with date picker, time input, and mata kuliah selection. |
| Log Sesi Module | modules/LogSesi/ + modules/TambahLogSesi/ | Session log management. LogDataTable with filters for listing logs. LogSesiForm for creating logs with participant count, session selection, and image proof upload. Uses Zod schema for validation. |
| Data Table | components/elements/table/DataTable.tsx | Generic reusable data table built on TanStack React Table with FilterBar, Pagination, and ActionButtons. Used across sessions and logs views. |
| Form Components | components/elements/form/ | Suite of reusable RISTEK-branded form inputs: RistekInput, RistekCalendar, RistekCalendarModal, RistekCombobox, RistekDropdownFilter, RistekFileInput, RistekMultiSelect, RistekTimeInput. Built on top of Radix UI and RSuite primitives. |
βοΈ Operational Playbook
Infrastructureβ
- Cloud Provider: Vercel
- Production Deployment: Push to main β GitHub Actions (deploy.yml) β Vercel production deploy
- Staging Deployment: Push to staging β GitHub Actions (staging.yml) β Vercel preview deploy
- Image CDN: Next.js Image Optimization with allowed remote patterns: localhost:8000, localhost:9000, stg.api.classtutor.ristek.cs.ui.ac.id, storage.ristek.cs.ui.ac.id
- Server Actions: Body size limit set to 10mb (for file uploads)
Environment Variablesβ
(example)
| Key | Description | Default (Dev) | Sensitive? |
|---|---|---|---|
| NEXT_PUBLIC_API_URL | Backend API base URL | β | No |
| NEXT_PUBLIC_APP_URL | Frontend base URL (used for SSO service URL and logout redirect) | β | No |
| NODE_ENV | Environment (controls cookie secure flag) | development | No |
| WEBDEV_VERCEL_TOKEN | Vercel deploy token (GitHub Actions secret) | β | Yes |
| ORG_ID | Vercel organization ID (GitHub Actions secret) | β | Yes |
| PROJECT_ID | Vercel project ID (GitHub Actions secret) | β | Yes |
πQuestions
π List of frequently asked questions or question that need to be answered that is related to this initiative ..