Migrate Calendar interface patterns
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { RefreshCw, RotateCcw, ScanSearch, Trash2 } from "lucide-react";
|
||||
import {
|
||||
ActionBlockerHint,
|
||||
Button,
|
||||
ConfirmDialog,
|
||||
Dialog,
|
||||
DismissibleAlert,
|
||||
DocumentationHelpLink,
|
||||
SegmentedControl,
|
||||
StatusBadge,
|
||||
type ApiSettings,
|
||||
@@ -17,6 +19,10 @@ import {
|
||||
type CalendarSyncSource,
|
||||
} from "../../api/calendar";
|
||||
import { dateTimeLabel, errorText } from "./calendarViewModel";
|
||||
import {
|
||||
CALENDAR_I18N,
|
||||
CALENDAR_RECOVERY_DOCUMENTATION,
|
||||
} from "./interfacePatterns";
|
||||
|
||||
type OutboxFilter = "unresolved" | "all";
|
||||
type RecoveryAction = "retry" | "reconcile" | "discard";
|
||||
@@ -94,7 +100,7 @@ export function CalendarOutboxDialog({
|
||||
onClose={onClose}
|
||||
footer={
|
||||
<>
|
||||
<Button type="button" onClick={() => void load()} disabled={loading || Boolean(busyOperationId)}>
|
||||
<Button type="button" onClick={() => void load()} disabled={loading || Boolean(busyOperationId)} disabledReason={loading ? CALENDAR_I18N.loading : busyOperationId ? CALENDAR_I18N.saving : undefined}>
|
||||
<RefreshCw size={16} className={loading ? "calendar-sync-spin" : undefined} /> i18n:govoplan-calendar.refresh.56e3badc
|
||||
</Button>
|
||||
<Button type="button" onClick={onClose} disabled={Boolean(busyOperationId)}>
|
||||
@@ -105,6 +111,7 @@ export function CalendarOutboxDialog({
|
||||
>
|
||||
<div className="calendar-outbox-body">
|
||||
<p className="calendar-outbox-calendar-name">{calendar.name}</p>
|
||||
<DocumentationHelpLink reference={CALENDAR_RECOVERY_DOCUMENTATION} />
|
||||
{error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>}
|
||||
<div className="calendar-outbox-toolbar">
|
||||
<SegmentedControl<OutboxFilter>
|
||||
@@ -191,23 +198,29 @@ function RecoveryActions({
|
||||
{available.length > 0 && (
|
||||
<div className="calendar-outbox-actions">
|
||||
{available.includes("retry") && (
|
||||
<Button type="button" onClick={() => onRecover("retry")} disabled={busy}>
|
||||
<Button type="button" onClick={() => onRecover("retry")} disabled={busy} disabledReason={busy ? CALENDAR_I18N.saving : undefined}>
|
||||
<RotateCcw size={15} /> i18n:govoplan-calendar.retry.3fda8f1c
|
||||
</Button>
|
||||
)}
|
||||
{available.includes("reconcile") && (
|
||||
<Button type="button" onClick={() => onRecover("reconcile")} disabled={busy}>
|
||||
<Button type="button" onClick={() => onRecover("reconcile")} disabled={busy} disabledReason={busy ? CALENDAR_I18N.saving : undefined}>
|
||||
<ScanSearch size={15} /> i18n:govoplan-calendar.reconcile.6c595f64
|
||||
</Button>
|
||||
)}
|
||||
{available.includes("discard") && (
|
||||
<Button type="button" variant="danger" onClick={() => onRecover("discard")} disabled={busy}>
|
||||
<Button type="button" variant="danger" onClick={() => onRecover("discard")} disabled={busy} disabledReason={busy ? CALENDAR_I18N.saving : undefined}>
|
||||
<Trash2 size={15} /> i18n:govoplan-calendar.discard.23a76911
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{!available.length && unavailableReason && <p className="calendar-form-note">{unavailableReason}</p>}
|
||||
{!available.length && unavailableReason && (
|
||||
<ActionBlockerHint
|
||||
tone="info"
|
||||
reason={{ summary: unavailableReason }}
|
||||
documentation={CALENDAR_RECOVERY_DOCUMENTATION}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user