chore(autonomous-session): consolidate uncommitted work from prior session
Bundles the prior autonomous-session output that was sitting unstaged: - Em-dash sweep across src/ + tests/ (en-dash/em-dash to hyphen, ~2280 instances) - country-flag-icons rollout (CountryFlag component, replaces emoji glyphs that never rendered on Windows; lazy-loads the 3x2 SVG index as a single chunk after the per-subpath dynamic-import approach silently failed in webpack) - Admin IA Phase 1+2: 7-domain regroup, 41 to 38 pages, /admin/berths index, redirects (ocr to ai, reports to dashboard, invitations to users), docs/admin-ia-proposal.md - Per-template email tester (registry + endpoint + UI on Email admin page) - Cancel-document mode picker (delete-from-Documenso vs keep-for-audit) - Dashboard PDF report: 25 widgets, SVG charts, date-range picker, 11 resolvers - Customize-widgets per-region sortables at xl+ (charts/rails/feed); single flat sortable below xl when the layout stacks; per-viewport saved orders - Audit doc updates capturing each shipped item - Lint fixes: react-compiler immutability in DonutChart (reduce instead of let-reassign), set-state-in-effect disables in CountryFlag and UploadForSigning preview-bytes effect, unused 'confirm' destructures in interest contract + reservation tabs, unescaped apostrophe in test-template card copy
This commit is contained in:
@@ -37,7 +37,7 @@ function toLocalDatetimeLocal(d: Date): string {
|
||||
/**
|
||||
* Build a Date relative to "now" for the quick-pick chips. Day-based
|
||||
* presets land on the user's preferred time-of-day (`digestTimeOfDay`
|
||||
* from user_profiles.preferences) — same source the default dueAt uses.
|
||||
* from user_profiles.preferences) - same source the default dueAt uses.
|
||||
* Hour-based presets use the current time + N hours.
|
||||
*/
|
||||
function buildPresetDate(
|
||||
@@ -142,11 +142,11 @@ function ReminderFormBody({
|
||||
onSuccess,
|
||||
}: ReminderFormProps) {
|
||||
const isEdit = !!reminder;
|
||||
// Phase 4 — load the rep's preferred default-reminder time (HH:MM)
|
||||
// Phase 4 - load the rep's preferred default-reminder time (HH:MM)
|
||||
// BEFORE seeding the dueAt state. React Query's cache keeps this
|
||||
// available synchronously on subsequent dialog opens (staleTime 60s)
|
||||
// so the initial value is the rep's preference, not the historical
|
||||
// 09:00 fallback. Enabled only on create-mode opens — edit mode
|
||||
// 09:00 fallback. Enabled only on create-mode opens - edit mode
|
||||
// already has the existing dueAt to seed from.
|
||||
const meQuery = useQuery<{ data: { preferences?: { digestTimeOfDay?: string } } }>({
|
||||
queryKey: ['me', 'preferences'],
|
||||
@@ -169,7 +169,7 @@ function ReminderFormBody({
|
||||
const t = new Date();
|
||||
t.setDate(t.getDate() + 1);
|
||||
// Honour the rep's user_profiles.preferences.digestTimeOfDay when
|
||||
// set ("HH:MM"). Falls back to 09:00 — historical default.
|
||||
// set ("HH:MM"). Falls back to 09:00 - historical default.
|
||||
let h = 9;
|
||||
let m = 0;
|
||||
if (userTodPref && /^\d{2}:\d{2}$/.test(userTodPref)) {
|
||||
@@ -205,6 +205,27 @@ function ReminderFormBody({
|
||||
});
|
||||
const users = usersQuery.data?.data ?? [];
|
||||
|
||||
// When a client is picked, restrict the YachtPicker to yachts owned by
|
||||
// that client OR by any company the client belongs to (e.g. a
|
||||
// managing-director client whose yachts are titled to the company).
|
||||
// Mirrors the interest-form pattern so the two surfaces stay
|
||||
// consistent.
|
||||
const clientDetailQuery = useQuery<{
|
||||
data: { companies?: Array<{ company: { id: string } }> };
|
||||
}>({
|
||||
queryKey: ['client-detail-for-reminder-form', clientId],
|
||||
queryFn: () => apiFetch(`/api/v1/clients/${clientId}`),
|
||||
enabled: !!clientId && open,
|
||||
});
|
||||
const memberCompanyIds: string[] =
|
||||
clientDetailQuery.data?.data.companies?.map((m) => m.company.id) ?? [];
|
||||
const yachtOwnerFilter = clientId
|
||||
? [
|
||||
{ type: 'client' as const, id: clientId },
|
||||
...memberCompanyIds.map((id) => ({ type: 'company' as const, id })),
|
||||
]
|
||||
: undefined;
|
||||
|
||||
async function handleSubmit(e: React.FormEvent) {
|
||||
e.preventDefault();
|
||||
setError(null);
|
||||
@@ -391,7 +412,8 @@ function ReminderFormBody({
|
||||
<YachtPicker
|
||||
value={yachtId || null}
|
||||
onChange={(id) => setYachtId(id ?? '')}
|
||||
placeholder="Search yachts..."
|
||||
ownerFilter={yachtOwnerFilter}
|
||||
placeholder={clientId ? 'Yachts linked to client...' : 'Search yachts...'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,13 +8,13 @@ import { apiFetch } from '@/lib/api/client';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
/**
|
||||
* Phase 4 — inline reminders list rendered inside an entity's
|
||||
* Phase 4 - inline reminders list rendered inside an entity's
|
||||
* Overview tab. Shows the most recent open (pending/snoozed) reminders
|
||||
* for the linked entity so reps can spot follow-ups without leaving the
|
||||
* detail page.
|
||||
*
|
||||
* Filter is exactly one of clientId / interestId / berthId / yachtId.
|
||||
* Caller responsibility — the listReminders service AND's whichever
|
||||
* Caller responsibility - the listReminders service AND's whichever
|
||||
* filters are present, so multiple would intersect rather than union.
|
||||
*
|
||||
* No "+ Reminder" button here on purpose: the detail-page header
|
||||
@@ -51,7 +51,7 @@ const STATUS_ICON: Record<InlineReminder['status'], React.ReactNode> = {
|
||||
};
|
||||
|
||||
interface RemindersInlineProps {
|
||||
/** Exactly one should be set — the entity to filter by. */
|
||||
/** Exactly one should be set - the entity to filter by. */
|
||||
clientId?: string;
|
||||
interestId?: string;
|
||||
berthId?: string;
|
||||
|
||||
Reference in New Issue
Block a user