mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-09-09 04:48:19 +00:00
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.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import type { LicenseTemplate } from '@ema-platform/api';
|
||||
|
||||
/**
|
||||
* Editor state for the selected version.
|
||||
*
|
||||
* Selection defaults to the live design because that is the one staff usually
|
||||
* open, and the fields reset whenever the selection changes so an edit can
|
||||
* never leak from one version into another.
|
||||
*/
|
||||
export function useTemplateDraft(templates: LicenseTemplate[]) {
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
const [source, setSource] = useState('');
|
||||
const [name, setName] = useState('');
|
||||
const [landscape, setLandscape] = useState(true);
|
||||
const [backgroundUrl, setBackgroundUrl] = useState('');
|
||||
const editorRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
const selected = useMemo(
|
||||
() => templates.find((tpl) => tpl.id === selectedId) ?? null,
|
||||
[templates, selectedId],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!templates.length) {
|
||||
setSelectedId(null);
|
||||
return;
|
||||
}
|
||||
if (selectedId && templates.some((tpl) => tpl.id === selectedId)) return;
|
||||
const published = templates.find((tpl) => tpl.status === 'PUBLISHED');
|
||||
setSelectedId((published ?? templates[0]).id);
|
||||
}, [templates, selectedId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selected) return;
|
||||
setSource(selected.hbsSource);
|
||||
setName(selected.name);
|
||||
setLandscape(selected.pageOptions?.landscape ?? true);
|
||||
setBackgroundUrl(selected.backgroundUrl ?? '');
|
||||
}, [selected]);
|
||||
|
||||
const isPublished = selected?.status === 'PUBLISHED';
|
||||
const dirty =
|
||||
Boolean(selected) &&
|
||||
(source !== selected?.hbsSource ||
|
||||
name !== selected?.name ||
|
||||
landscape !== (selected?.pageOptions?.landscape ?? true) ||
|
||||
backgroundUrl !== (selected?.backgroundUrl ?? ''));
|
||||
|
||||
/** Inserts a placeholder where the caret is, rather than at the end. */
|
||||
function insertVariable(key: string) {
|
||||
const el = editorRef.current;
|
||||
const token = `{{${key}}}`;
|
||||
if (!el) {
|
||||
setSource((prev) => prev + token);
|
||||
return;
|
||||
}
|
||||
const start = el.selectionStart ?? source.length;
|
||||
const end = el.selectionEnd ?? start;
|
||||
setSource(source.slice(0, start) + token + source.slice(end));
|
||||
requestAnimationFrame(() => {
|
||||
el.focus();
|
||||
el.setSelectionRange(start + token.length, start + token.length);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
selected,
|
||||
selectedId,
|
||||
setSelectedId,
|
||||
source,
|
||||
setSource,
|
||||
name,
|
||||
setName,
|
||||
landscape,
|
||||
setLandscape,
|
||||
backgroundUrl,
|
||||
setBackgroundUrl,
|
||||
editorRef,
|
||||
isPublished,
|
||||
dirty,
|
||||
insertVariable,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user