Features
User-facing and admin features and their routes.
User features
Home
Landing + authenticated home
Videos & Articles
Educational content browse + save
Forum
Preference-filtered peer forum
Reminders
Medication, meal, therapy, consultation
Faskes Finder
Geolocation-based stroke facilities
Teleconsultation
Deep-links to telehealth apps
Profile & Notifications
Edit profile, push notifs
Remote config
Per-province home layout (admin)
Home
/—HomeNotLoggedIn: latest 2 videos + 2 articles, 5-icon menu grid, emergency button (dials the per-province number fromGET /api/emergency/nearby, falling back totel:112), FAQ, user guide./homelogin—HomeLoggedIn: same content + avatar, notifications bell, hamburger sidebar (language, profile, privacy, FAQ, logout), push registration on mount.
The section order and visibility of both home pages is driven by remote config — see Remote config. Resolution: GPS → inputted domicile → DEFAULT_CONFIG.
Videos & Articles
/videos,/video/:id— educational videos (YouTube embed) with comments./articles,/article/:id— articles rendered from react-quill content, with likes and comments.- Video thumbnails come straight from the API (largest real resolution) and render through
<SmartThumb>(src/utils/youtube.js) — a failed load falls back to a placeholder; it never guessesmaxresURLs, so low-res videos (e.g. Me at the zoo) still show their real thumbnail. - Save-for-later supported on both (see backend
POST /api/articles/save,POST /api/youtube/save).
Faskes finder
/faskes (FaskesStroke.js) — uses the browser geolocation to find nearby stroke facilities (GET /api/faskes/nearby) and doctors. Doctors come from GET /api/dokter/nearby (province-matched, sorted by distance, each card shows a ⚲ km badge); on failure it falls back to GET /api/dokter (unsorted, no badges). A radius dropdown on the Dokter tab (Semua / ≤5 / ≤10 / ≤25 / ≤50 km) filters client-side — default "Semua" hides nobody. Tabs for Faskes/Dokter, Google Maps links, call buttons, telemedicine links.
Teleconsultation
/telekonsultasi (Telekonsultasi.js) — redirects to telehealth apps: Halodoc, Alodokter, KlikDokter, Dkonsul. Uses deep links with app-store fallback.
Profile & notifications
/profile,/edit-profile— profile + image upload (POST /api/profilemultipart), preferences, roles./notif— push notification list, mark-as-read./reminders— reminder list with type filter and medicine grouping.
Admin panel
Navigation via AdminSidebar (11 menu items + help + logout):
| Area | Routes |
|---|---|
| Overview | /admin/overview — aggregate dashboard (totals, growth, activity, exports) |
| Videos | /admin/video, /admin/video/upload, /admin/video/edit/:videoId — upload/edit forms show a live thumbnail preview under the URL field (parsed from the URL; edit page falls back to the stored thumbnail) |
| Articles | /admin/article, /admin/article/upload, /admin/article/edit/:id |
| Communities | /admin/community, /admin/community/add, /admin/community/update/:id |
| Facilities & Doctors | /admin/faskes, /admin/faskes/add, /admin/faskes/edit/:place_id, /admin/faskes/add-doctor, /admin/faskes/edit-doctor/:id |
| Admin users | /admin/adminlist, /admin/adminlist/add, /admin/adminlist/edit/:username |
| Users | /admin/userlist, /admin/users/:id/edit (roles, caregiver links) |
| Categories | /admin/category (CRUD) |
| Emergency numbers | /admin/emergency-number (per-province) |
| Remote config | /admin/remote-config (per-province home layout) |
| Caregiver–patient | /admin/caregiver-patient (pairing management) |
Overview dashboard
/admin/overview (AdminOverview.js) — aggregate statistics pulled from GET /api/admins/overview: user/admin totals, per-province distribution, monthly user growth, top activities, forum & reminder category counts, and recent activity. A date-range filter (start/end) scopes every query. The page also exports reports (GET /api/admins/export/:report?format=) — users, admins, activity-logs, domicile as CSV / PDF / XLSX.
Emergency numbers (per-province)
/admin/emergency-number (AdminProvince.js) — admin CRUD for per-province emergency phone numbers (POST/PUT/DELETE /api/emergency). The public home page calls GET /api/emergency/nearby?lat=&lng= with the user's GPS, reverse-geocodes to a province, and dials that province's number; it falls back to tel:112 when there is no match. Admins must re-enter the numbers here after the migration — old static emergency handling was replaced by this table.
Remote config (per-province home layout)
/admin/remote-config (AdminRemoteConfig.js) — lets an admin control the order and visibility of home-page sections per province. Each province gets a full sections: [{id, enabled, order}] config (replaced wholesale on save via PUT /api/province-config/:province). The special province "default" controls the logged-out home page.
Province resolution on the home page, in priority order:
- GPS —
GET /api/province-config/nearby?lat=&lng=reverse-geocodes the user's location. - Inputted domicile — the province the user entered at registration (fallback when GPS fails).
DEFAULT_CONFIG— built-in defaults insrc/utils/homeSections.js(final fallback).
The page uses @dnd-kit for drag-to-reorder, a live phone-shaped preview (HomePreview.jsx) showing header/greeting/sections/footer with all buttons disabled, and a toggle per section.
Guided tours (driver.js)
/admin/remote-config, /admin/emergency-number, /admin/faskes, /admin/faskes/add and /admin/faskes/edit/:place_id ship a driver.js guided tour (shared hook: src/hooks/useTour.js, usePageTour + HelpButton). It auto-triggers on the first visit to each page (tracked in localStorage, so it persists across sessions) and a Bantuan ("?") button in the heading repeats it on demand. Tours start only after the page's data has loaded (tours delay until the target elements exist in the DOM).
Faskes admin forms
/admin/faskes/add and /admin/faskes/edit/:place_id accept three ways to set a location: typing lat, lng manually, pasting a Google Maps link (parsed by src/utils/gmaps.js — also auto-fills the name), or clicking the Leaflet map (pin moves, coordinates fill, address reverse-geocodes via the existing debounce). On add, the backend rejects duplicates: same place_id, or an existing faskes within 100 m with a similar name.
Superadmin panel
/superadmin (superAdmin/SuperAdmin.js) — a raw SQL database browser: list tables, view data, execute arbitrary SQL, export to CSV. Login is a separate prompt()-based flow hitting /api/superadmin/login.
Powerful and dangerous
The superadmin panel executes arbitrary SQL. It is gated by a separate JWT (role: "superadmin") and shows a warning banner.