Commit Graph

273 Commits

Author SHA1 Message Date
mihretue
e97e12d979 Merge remote-tracking branch 'origin/certficate' into feature/exam-attempt-domain 2026-08-17 11:19:17 +00:00
mihretue
4a7d36369f fix(exam): print real MCQ options, evaluation-method-aware cutting point check
Print showed blank A/B/C/D fill-in lines for every CHOICE question instead
of the real options — the detail page never fetched option data at all
(GET /exams/:id?i=questions, no nested options), and the print template
hardcoded the blanks regardless. Now requests
?i=questions,questions.options and prints the real option text, falling
back to blank lines only when a question genuinely has none on record.

Also fixed the print-time cutting-point guard: it compared raw point sum
to cutting point regardless of evaluationMethod, wrongly blocking valid
low-point-sum PERCENTAGE papers from printing. Now branches the same way
RecordResultModal's grading preview already does, and surfaces the
matching backend validation error (paper_cannot_reach_cutting_point) added
server-side for the same reason.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-17 09:43:09 +00:00
Nati
7f45df04e0 feat(seafarer-registration): remove standalone registration page and redirect to licensing flow; update profile handling and eligibility checks 2026-08-17 09:15:39 +00:00
mihretue
4f692c6bcf fix(exam): stop Create/Update Exam form from silently failing to submit
Three bugs compounded into a button that looked unwired:

- cuttingPoint carried a native HTML required attribute while sitting on
  the hidden Settings tab (Mantine keeps inactive tab panels mounted with
  display:none). The browser blocked form submission entirely, silently
  - no toast, no error, nothing. Replaced required with withAsterisk and
  moved validation into JS.
- Manual required-field validation never checked type/form/adminMethod/
  evalMethod/cuttingPoint at all, so even without the native block above
  a half-filled Settings tab would silently no-op. Validation now covers
  every required field on both tabs and switches to whichever tab has
  the problem.
- Filling only the English Direction field (leaving Amharic blank) passed
  frontend validation but the backend hard-rejects it, producing a 400
  with a confusing error. Frontend now requires both-or-neither, matching
  the same rule already applied to MCQ options.

Also translates the previously hardcoded validation message in both
locales.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-17 08:48:32 +00:00
mihretue
84ff644ebb fix(question): show both language fields for MCQ options
Options editor used a single toggle-based bilingual field (BilingualInput)
that swapped English/Amharic in place via a tiny, easy-to-miss button.
Authors were filling English only and never noticing Amharic was empty.

- QuestionOptionsEditor: show separate always-visible English/Amharic
  TextInputs per option instead of the toggle field.
- BilingualInput (shared): for other callers still using the toggle,
  add a tooltip and a red dot indicator when the hidden language is
  empty, so the gap is visible without switching.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-17 08:26:21 +00:00
Nati
3e3d20174c feat(certificates): enhance eligibility checks for CoC/CoP application with tooltips and alerts 2026-08-17 08:19:33 +00:00
Nati
ad9b14d716 fix(profile): change update method from PATCH to PUT for profile updates 2026-08-17 07:45:22 +00:00
Nati
ef3a59e617 Information Update 2026-08-17 07:36:44 +00:00
Nati
1f2261a68b feat(seafarer-registration): update profile handling and address submission logic 2026-08-17 07:23:23 +00:00
Nati
4ed2057a45 feat(onboarding): enhance navigation after registration by using selected keys 2026-08-17 07:11:07 +00:00
nati14575
c698f381b9 fix(api): update BASE_API_URL to use localhost:3000 for consistency 2026-08-17 09:58:51 +03:00
fitse-yotor
fa7eb3dc5f feat(backoffice): restore Mengestab's seafarer register and wire it up
The approved single-page register -- with the detail modal that shows a
seafarer's full standing -- had been replaced by a three-file grid that
carried no profile view. That is why the seafarer profile appeared
missing from the backoffice entirely.

Restores his page and points it at /seafarer-registry. The list is
served whole and filtered in the browser: the filters are instant facets
over a page-sized list, and a round trip per keystroke would make the
search feel slower than the data it searches.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 07:15:08 +03:00
fitse-yotor
c52d739e18 fix(portal): stop the profile gate hiding the approved registration wizard
/seafarer-registration was wrapped in RequireSeafarerProfile, which sends
an applicant with an incomplete profile to /profile first. That gate
belongs to the replacement design, where registration is filled in from
the profile. Mengestab's approved wizard asks for those same personal,
identity and contact details itself across its four steps, so the gate
bounced the applicant out before they ever saw the form -- which is why
the approved UI looked missing rather than merely unreachable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 07:05:43 +03:00
fitse-yotor
29f400618e feat(portal): wire the certificates and endorsement screens to the API
Both listed hardcoded samples -- a CoC application permanently awaiting
examination, an endorsement from Greece. They now show the seafarer's
own certificates and applications.

Status badges are keyed by the workflow's own values rather than display
strings, so a status the map has not seen falls back to grey instead of
rendering colourless, and the label is derived from the status itself
rather than stored beside it where the two can disagree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 06:57:36 +03:00
fitse-yotor
35c7987047 feat(portal): wire the medical, BST and seaman-book screens to the API
These three carried hardcoded sample data -- a certificate expiring in
2026, a fully-ticked training list, an eligibility checklist that always
passed. They now read the portal endpoints and show the seafarer's own
record.

Expiry is taken from the server rather than recomputed in the browser:
it is the same figure the eligibility gate uses, and a client clock that
is wrong or in another timezone would otherwise show a seafarer a
different number than the officer sees. Eligibility likewise -- the
screen asks whether it may apply rather than deciding for itself, so it
cannot offer a button the API then refuses.

The seaman-book stepper is derived from the application's status instead
of a stored timeline, because the status is what the workflow actually
moves; a second record of the same journey would only drift out of step.
Status colours are keyed by the workflow's own values, so an unmapped
status falls back to grey rather than vanishing.

/medical and /basic-safety-training had no route at all -- both silently
fell through to the dashboard, which is why the pages looked unreachable
rather than merely unwired.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 01:18:59 +03:00
fitse-yotor
702496202f fix(portal): make the restored seafarer/vessel UI compile
Restores three pages the current router imports that Mengestab's branch
never had -- MySeaRecordsPage, VesselTransferPage,
VesselRegistrationStatusPage -- from history, along with the vessel
mock module the status page reads.

Also fixes a dead comparison in VesselRegistrationPage: the block only
renders while a registration is *not* approved, so the nested
`status === 'Approved'` inside it is provably false and TypeScript
refuses it. Rendering behaviour is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 23:27:27 +03:00
fitse-yotor
eabaae36a0 feat(portal): restore Mengestab's client-approved seafarer and vessel UI
Copied verbatim from the pre-override branch so the approved screens are
recoverable at this exact commit before any wiring changes them.

Brings back the richer flows the client signed off: a four-step seafarer
registration wizard with bilingual inputs and an Ethiopic date picker,
the vessel-owner portal (its own register/login/dashboard), ownership
transfer, and the seaman book, certificate, medical and endorsement
screens.

Six of these pages already call an API; ten are mockups carrying
hardcoded data. Both are committed as-is here -- the wiring that follows
is a separate commit so the diff shows exactly what changed from what
the client approved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 23:19:08 +03:00
fitse-yotor
f294f67ced fix(portal,backoffice): six reported issues in registration and the designer
Seafarer and vessel registration were filtered out of the operations
step by `requiresOperatorMode !== false`, so someone registering as a
seafarer or vessel owner landed on an onboarding screen that did not
describe them. Both now appear, grouped apart from the company modes:
declaring "I am a seafarer" is a different kind of statement from "my
company forwards freight".

The designer's preview was gated on the Handlebars source alone, which a
canvas layout does not have until the server compiles it on save -- so
the button was dead for exactly the designs the canvas exists for.

Editing looked broken rather than deliberately read-only: every seeded
template is PUBLISHED, and a published design is immutable because
certificates were issued from it. Says so, and offers the new-version
action that is the way forward.

Reviewing officers saw company, capital and staff tabs on seafarer
certificate applications, because PRESENTATION is keyed by the generic
licence keys and the fifty-odd rank-specific CoC/CoP keys fell through
to the company default. Matched by prefix instead, so a certificate
configured tomorrow gets the right presentation without a code change.

Seaman book and BTC are wired to the newly seeded licence types and no
longer marked "soon".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 22:21:00 +03:00
fitse-yotor
c58a727a96 Merge branch 'feature/seaman' of https://github.com/Tria-plc/emaui into certficate 2026-08-15 12:44:39 +03:00
fitse-yotor
0ac75669d4 feat: add ExamStageActions component for exam fee handling
- Implemented ExamStageActions component to manage actions related to exam booking and payment based on application status.
- Added mock-base-query for development, providing a partial mock backend for various API endpoints.
- Introduced mock-data for simulating responses in the mock-base-query, covering profiles, vessels, applications, licenses, exams, and notifications.
2026-08-15 11:51:14 +03:00
mihretue
4edce751ee feat(exam): candidate exam-taking experience (Phase 4)
New portal feature apps/portal/src/app/features/exam-attempt/, following
the repo's existing folder convention (pages/<Page>/index.tsx, components/,
types/, hooks/ — matches the payments feature's hooks/ precedent):

- types/exam-attempt.ts — response/local-state shapes
- hooks/useExamAttempt.ts — all API orchestration: load (registration +
  attempt), start/resume, per-question autosave (immediate on MCQ select,
  debounced+flushed-on-navigation for essay text), local countdown seeded
  from the server's serverTime/remainingSeconds, submit, and resync from
  the server whenever a write is refused as expired/already-submitted
- components/ExamInstructions, ExamTimer, ExamQuestionNav,
  ExamQuestionDisplay, ExamCompletion — one concern per file, not a single
  page dump
- pages/ExamAttemptPage — thin view layer over the hook

Flow: /exams (existing) gets a 'Take exam' action on eligible registration
rows → /exams/:examId/take, which shows instructions before an attempt
exists, the live exam screen while IN_PROGRESS, and a no-score completion
screen once SUBMITTED/EXPIRED (never fabricates a result — grading
doesn't exist yet).

Security note: RequirePermission on the route and disabled inputs after
local timeout are UI conveniences only. Every save/submit is independently
re-checked by the backend's ownership + applyExpiry() on each call: a
client that skipped the UI entirely and hit the API directly would be
bound by exactly the same rules.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 09:17:09 +00:00
estifanos
e0b3a4887a feat: add internationalization support for auth components and pages, including translations for Amharic and English 2026-08-14 07:54:30 +00:00
estifanos
de04ed64b3 feat: remove certificate verification page and related API, update landing page links 2026-08-14 07:34:35 +00:00
estifanos
d6b813b697 feat: add landing page copy and styles for English and Amharic versions
- Introduced `landing-copy.ts` containing text for the public landing page, supporting both English and Amharic languages.
- Added `landing.css` for styling the landing page, ensuring scoped styles to prevent conflicts with other app styles.
- Implemented smooth scrolling and animations for a better user experience.
2026-08-14 07:20:42 +00:00
mihretue
14b5bb83f9 feat(question): MCQ options authoring editor (Phase 2 domain foundation)
Backend now supports MCQ options + a separate answer-key table
(PUT /questions/:id/options). Frontend side of that, authoring only —
no candidate exam-taking UI.

- Question type gains options?: QuestionOption[] (no correctness field —
  the API never returns one, matching the backend's split-table design)
- New question-api hooks: getQuestionWithOptions, setQuestionOptions
- New QuestionOptionsEditor component (separate file, not inlined into
  QuestionPage) — add/remove/reorder options, mark correct, bilingual text
- Wired into the question edit form, shown only for an existing CHOICE
  question (options attach to an id, matching the backend's replace
  endpoint)
- en/am i18n strings for the new editor

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 19:28:03 +00:00
mihretue
d98d6a71fe fix(result): gate record/save buttons behind RECORD_EXAM_RESULT
Record Result (POST /results) and the detail-modal Save (PUT /results/:id)
had no RequirePermission gate, unlike every other action on this page —
both routes are backend-guarded (RECORD_EXAM_RESULT, or
RECORD_EXAM_RESULT|MODERATE_EXAM_RESULT for the update), the buttons just
never mirrored it client-side.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 17:17:14 +00:00
Nati
6852fc86c6 feat: implement permission-based access control across various pages and components
- Added RequirePermission component to manage access based on user permissions.
- Integrated permission checks in MySeaRecordsPage, SeafarerRegistrationPage, VesselRegistrationPage, WaiverPage, and PortalLayout.
- Updated router to enforce permissions for specific routes.
- Introduced PORTAL_PERMISSIONS and LICENSE_PERMISSIONS constants for consistent permission management.
- Enhanced usePermissions hook to fetch permissions from the server and determine access rights.
- Refactored UI components to conditionally render based on user permissions, improving security and user experience.
2026-08-13 12:58:11 +00:00
Nati
220ed2d018 Merge branch 'dev' of github.com:Tria-plc/emaui into Refactor
Resolved by unifying on the lib/data AdvancedTable (PR #10) as the canonical
table component: kept its API plus teammate i18n/feature work, kept the
folder-per-table structure (index.tsx + columns.tsx + actions.tsx) across all
27 tables, removed the parallel lib/table implementation, and fixed
pre-existing compile breaks in ExamDetailPage/QuestionAssigner/RecordResultModal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-13 11:31:27 +00:00
Nati
2af9e60800 feat(vessel-registration): add vessel registration page with incident reporting and certificate download functionality
feat(waiver): implement waiver page with application tracking and letter download feature

feat(ui): introduce AdvancedTable component for enhanced table functionality across the application

chore: update package-lock.json to remove unnecessary dependencies
2026-08-13 09:11:50 +00:00
estifanos
2fa55965e1 feat: enhance internationalization support across various components and pages 2026-08-12 12:30:22 +00:00
estifanos
31c52c02e0 feat: introduce useLocalized hook for bilingual value retrieval.(localization round 2)
- Added useLocalized hook to provide a stable function for retrieving bilingual values based on the current language.
- Updated various components across the portal and backoffice to utilize the new useLocalized hook for consistent bilingual label rendering.
- Refactored localized function in licensing.helpers to handle empty Amharic strings correctly.
- Enhanced localization handling in LicenseApplicationPage, ProfilePage, and other components to ensure proper language switching.
2026-08-12 11:31:20 +00:00
Estifo77
faf58850f0 UI fixes 2026-08-12 14:17:29 +03:00
estifanos
7242f8425a feat: add internationalization support for WaiverPage with translations for English and Amharic 2026-08-12 11:04:47 +00:00
estifanos
8f2dcb30f0 feat: add internationalization support for seafarer registry
- Integrated i18n for seafarer registry page, including translations for various UI elements and statuses.
- Updated SeafarerDetailDrawer and StatusModal components to utilize translation hooks.
- Enhanced user feedback messages for status updates and errors.
- Added new translations for Amharic and English locales, covering seafarer statuses, drawer labels, modal content, and table headers.
localization for backoffice
2026-08-12 10:55:14 +00:00
estifanos
9897a9bf78 feat: implement date display utility across various pages
- Added `useDateDisplayer` hook and `dateDisplayer` function to format dates consistently based on the user's language.
- Updated multiple components and pages in both backoffice and portal applications to utilize the new date display functionality, ensuring proper formatting for dates in lists, tables, and detail views.
- Introduced Ethiopian date formatting for Amharic language support.
- Refactored date handling in components such as ExamAppealsPage, ResultPage, SeafarerRegistryPage, and others to improve localization and user experience.
2026-08-12 10:22:39 +00:00
Estifo77
33935419fb cookie clearting fix 2026-08-12 12:34:09 +03:00
estifanos
7c9f78c680 feat: replace Paper with Modal in CertificationPage, ConfigurationPage, ExamPage, and QuestionPage for consistent UI 2026-08-12 07:55:43 +00:00
estifanos
d0bbfe30d1 feat: update MyApplicationsPage with AdvancedTable and add translations for table headers 2026-08-12 07:45:00 +00:00
estifanos
5aea4b1c9f feat: enhance MyApplicationsPage with segmented tabs and improved styling
- Added a new CSS module for MyApplicationsPage to style the segmented tab bar and clickable tiles.
- Implemented tab navigation for applications, licences, and apply sections, improving user experience.
- Introduced filtering options for applications, including search, status, and date range.
- Enhanced the display of application and licence information with new components and improved layout.
- Updated translations for the new features in both Amharic and English.
2026-08-12 07:37:53 +00:00
estifanos
362e6d88b4 feat: enhance PaymentConfigPage with refetch and loading state for license types 2026-08-12 07:37:19 +00:00
estifanos
bbb23f3bbf feat: replace Table with AdvancedTable for improved license type management in PaymentConfigPage 2026-08-12 07:35:43 +00:00
estifanos
0633ecc165 feat: implement applicant name fallback logic in licensing helpers and update MyApplicationsPage 2026-08-12 07:18:43 +00:00
estifanos
829dfed999 feat: add search and filter functionality to MyApplicationsPage 2026-08-12 07:15:21 +00:00
estifanos
7c3a25245f UI fixes 2026-08-11 11:48:09 +00:00
estifanos
1b0a21c683 feat: add page size selection to AdvancedTable and update useServerTable hook 2026-08-11 11:37:52 +00:00
Estifo77
0573e01769 UI fixes 2026-08-11 14:32:26 +03:00
estifanos
0fd78c7757 fix: update Badge component in LicenseQueuePage for consistent styling
feat: add siblings and boundaries props to pagination in AdvancedTable
2026-08-11 11:23:38 +00:00
estifanos
d7ecc86177 fix: restore vessel transfer logic and update vessel selection component(uncommenting) 2026-08-11 11:10:14 +00:00
estifanos
01899c0593 feat: implement endorsement types and update navigation for endorsement processing 2026-08-11 10:50:37 +00:00
estifanos
deb650f22f fix: update DocumentSlots component to include optional mode and use requirement.id as key 2026-08-11 10:35:49 +00:00