bugfix: some minor ui updates for invitation history dialog.
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
|||||||
type FeaturePermState,
|
type FeaturePermState,
|
||||||
} from '../../../components/staff/staff-permission-form';
|
} from '../../../components/staff/staff-permission-form';
|
||||||
import { Pencil, Trash2, Copy, Check, X } from 'lucide-react';
|
import { Pencil, Trash2, Copy, Check, X } from 'lucide-react';
|
||||||
|
import { DialogCloseButton } from '@/components/ui/common/DialogCloseButton';
|
||||||
import { useAuth } from '@/lib/hooks/useAuth';
|
import { useAuth } from '@/lib/hooks/useAuth';
|
||||||
import { staffApi, type StaffMemberDto } from '@/lib/api/staff';
|
import { staffApi, type StaffMemberDto } from '@/lib/api/staff';
|
||||||
import { Button } from '@/components/ui/common/Button';
|
import { Button } from '@/components/ui/common/Button';
|
||||||
@@ -603,9 +604,12 @@ export default function StaffPage() {
|
|||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="invite-staff-title"
|
aria-labelledby="invite-staff-title"
|
||||||
>
|
>
|
||||||
<h2 id="invite-staff-title" className="text-lg font-semibold text-text-primary">
|
<div className="flex items-start justify-between gap-3">
|
||||||
|
<h2 id="invite-staff-title" className="text-lg font-semibold text-text-primary pr-2">
|
||||||
Invite team member
|
Invite team member
|
||||||
</h2>
|
</h2>
|
||||||
|
<DialogCloseButton onClick={() => setInviteOpen(false)} />
|
||||||
|
</div>
|
||||||
<Input
|
<Input
|
||||||
label="Email"
|
label="Email"
|
||||||
type="email"
|
type="email"
|
||||||
@@ -650,7 +654,10 @@ export default function StaffPage() {
|
|||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
>
|
>
|
||||||
<h2 className="text-lg font-semibold text-text-primary">Edit member</h2>
|
<div className="flex items-start justify-between gap-3">
|
||||||
|
<h2 className="text-lg font-semibold text-text-primary pr-2">Edit member</h2>
|
||||||
|
<DialogCloseButton onClick={() => setEditing(null)} />
|
||||||
|
</div>
|
||||||
<p className="text-xs text-text-muted">{editing.email}</p>
|
<p className="text-xs text-text-muted">{editing.email}</p>
|
||||||
<Input label="Display name" value={editName} onChange={(e) => setEditName(e.target.value)} />
|
<Input label="Display name" value={editName} onChange={(e) => setEditName(e.target.value)} />
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { X } from 'lucide-react';
|
|
||||||
import { Button } from '@/components/ui/common/Button';
|
import { Button } from '@/components/ui/common/Button';
|
||||||
|
import { DialogCloseButton } from '@/components/ui/common/DialogCloseButton';
|
||||||
import { Dropdown } from '@/components/ui/common/Dropdown';
|
import { Dropdown } from '@/components/ui/common/Dropdown';
|
||||||
import type { AppointmentPurpose, AppointmentRecord } from '@/types/appointment';
|
import type { AppointmentPurpose, AppointmentRecord } from '@/types/appointment';
|
||||||
import { APPOINTMENT_PURPOSE_LABEL } from '@/components/ui/appointments/appointmentPurposeStyles';
|
import { APPOINTMENT_PURPOSE_LABEL } from '@/components/ui/appointments/appointmentPurposeStyles';
|
||||||
@@ -161,14 +161,7 @@ export function AppointmentBookingModal({
|
|||||||
<h2 id="appointment-modal-title" className="text-lg font-semibold text-text-primary pr-2">
|
<h2 id="appointment-modal-title" className="text-lg font-semibold text-text-primary pr-2">
|
||||||
{editingAppointment ? 'Edit appointment' : 'New appointment'}
|
{editingAppointment ? 'Edit appointment' : 'New appointment'}
|
||||||
</h2>
|
</h2>
|
||||||
<button
|
<DialogCloseButton onClick={onClose} />
|
||||||
type="button"
|
|
||||||
onClick={onClose}
|
|
||||||
className="rounded-[var(--radius-sm)] p-1.5 text-text-muted hover:text-text-primary hover:bg-background-secondary/80 focus:outline-none focus:ring-2 focus:ring-primary/35"
|
|
||||||
aria-label="Close"
|
|
||||||
>
|
|
||||||
<X className="h-5 w-5 icon-flat" />
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-sm text-text-secondary">
|
<p className="text-sm text-text-secondary">
|
||||||
|
|||||||
21
frontend/src/components/ui/common/DialogCloseButton.tsx
Normal file
21
frontend/src/components/ui/common/DialogCloseButton.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { X } from 'lucide-react';
|
||||||
|
|
||||||
|
type DialogCloseButtonProps = {
|
||||||
|
onClick: () => void;
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function DialogCloseButton({ onClick, className = '' }: DialogCloseButtonProps) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onClick}
|
||||||
|
className={`shrink-0 rounded-[var(--radius-sm)] p-1.5 text-text-muted hover:text-text-primary hover:bg-background-secondary/80 focus:outline-none focus:ring-2 focus:ring-primary/35 ${className}`}
|
||||||
|
aria-label="Close"
|
||||||
|
>
|
||||||
|
<X className="h-5 w-5 icon-flat" />
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Check, Copy } from 'lucide-react';
|
import { Check, Copy } from 'lucide-react';
|
||||||
|
import { DialogCloseButton } from '@/components/ui/common/DialogCloseButton';
|
||||||
import type { OrganizationInvitationHistoryItemDto } from '@/lib/api/organization';
|
import type { OrganizationInvitationHistoryItemDto } from '@/lib/api/organization';
|
||||||
import { canShareOrganizationInviteLink } from '@/components/invitations/organizationInviteLinks';
|
import { canShareOrganizationInviteLink } from '@/components/invitations/organizationInviteLinks';
|
||||||
import { Badge, organizationLinkStatusVariant } from '@/components/ui/common/Badge';
|
import { Badge, organizationLinkStatusVariant } from '@/components/ui/common/Badge';
|
||||||
import { Button } from '@/components/ui/common/Button';
|
|
||||||
import { Table } from '@/components/ui/common/Table';
|
import { Table } from '@/components/ui/common/Table';
|
||||||
|
|
||||||
function formatInvitationStatusLabel(status: OrganizationInvitationHistoryItemDto['status']): string {
|
function formatInvitationStatusLabel(status: OrganizationInvitationHistoryItemDto['status']): string {
|
||||||
@@ -49,18 +49,16 @@ export function InvitationHistoryDialog({
|
|||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50">
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50">
|
||||||
<div
|
<div
|
||||||
className="w-full max-w-3xl max-h-[90vh] overflow-y-auto rounded-[var(--radius-md)] border border-border bg-background-secondary p-6 shadow-xl space-y-4"
|
className="w-full max-w-[min(56rem,calc(100vw-17rem))] max-h-[90vh] overflow-y-auto rounded-[var(--radius-md)] border border-border bg-background-secondary p-6 shadow-xl space-y-4"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="invitation-history-title"
|
aria-labelledby="invitation-history-title"
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between gap-3">
|
<div className="flex items-start justify-between gap-3">
|
||||||
<h2 id="invitation-history-title" className="text-lg font-semibold text-text-primary">
|
<h2 id="invitation-history-title" className="text-lg font-semibold text-text-primary pr-2">
|
||||||
Invitation History
|
Invitation History
|
||||||
</h2>
|
</h2>
|
||||||
<Button type="button" size="sm" onClick={onClose}>
|
<DialogCloseButton onClick={onClose} />
|
||||||
Close
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{copyError && (
|
{copyError && (
|
||||||
|
|||||||
@@ -81,18 +81,18 @@
|
|||||||
--color-card-muted: #b6c6dd;
|
--color-card-muted: #b6c6dd;
|
||||||
--color-card-border: #29456a;
|
--color-card-border: #29456a;
|
||||||
|
|
||||||
--color-badge-default-bg: #1b2f4e;
|
--color-badge-default-bg: rgba(27, 47, 78, 0.32);
|
||||||
--color-badge-default-fg: #b6c6dd;
|
--color-badge-default-fg: #9eb1cb;
|
||||||
--color-badge-default-border: #3b5f8f;
|
--color-badge-default-border: rgba(59, 95, 143, 0.32);
|
||||||
--color-badge-success-bg: rgba(6, 78, 59, 0.45);
|
--color-badge-success-bg: rgba(6, 78, 59, 0.22);
|
||||||
--color-badge-success-fg: #86efac;
|
--color-badge-success-fg: #7dd3a8;
|
||||||
--color-badge-success-border: rgba(21, 128, 61, 0.5);
|
--color-badge-success-border: rgba(34, 100, 68, 0.28);
|
||||||
--color-badge-warning-bg: rgba(120, 53, 15, 0.48);
|
--color-badge-warning-bg: rgba(120, 53, 15, 0.22);
|
||||||
--color-badge-warning-fg: #fcd34d;
|
--color-badge-warning-fg: #dfc06a;
|
||||||
--color-badge-warning-border: rgba(180, 83, 9, 0.55);
|
--color-badge-warning-border: rgba(146, 88, 20, 0.28);
|
||||||
--color-badge-danger-bg: rgba(127, 29, 29, 0.42);
|
--color-badge-danger-bg: rgba(127, 29, 29, 0.22);
|
||||||
--color-badge-danger-fg: #fca5a5;
|
--color-badge-danger-fg: #e4a6a6;
|
||||||
--color-badge-danger-border: rgba(185, 28, 28, 0.52);
|
--color-badge-danger-border: rgba(153, 50, 50, 0.28);
|
||||||
|
|
||||||
--color-purpose-consultation-bg: rgba(139, 92, 246, 0.25);
|
--color-purpose-consultation-bg: rgba(139, 92, 246, 0.25);
|
||||||
--color-purpose-consultation-fg: #ddd6fe;
|
--color-purpose-consultation-fg: #ddd6fe;
|
||||||
@@ -139,18 +139,18 @@
|
|||||||
--color-card-muted: #b6c6dd;
|
--color-card-muted: #b6c6dd;
|
||||||
--color-card-border: #29456a;
|
--color-card-border: #29456a;
|
||||||
|
|
||||||
--color-badge-default-bg: #1b2f4e;
|
--color-badge-default-bg: rgba(27, 47, 78, 0.32);
|
||||||
--color-badge-default-fg: #b6c6dd;
|
--color-badge-default-fg: #9eb1cb;
|
||||||
--color-badge-default-border: #3b5f8f;
|
--color-badge-default-border: rgba(59, 95, 143, 0.32);
|
||||||
--color-badge-success-bg: rgba(6, 78, 59, 0.45);
|
--color-badge-success-bg: rgba(6, 78, 59, 0.22);
|
||||||
--color-badge-success-fg: #86efac;
|
--color-badge-success-fg: #7dd3a8;
|
||||||
--color-badge-success-border: rgba(21, 128, 61, 0.5);
|
--color-badge-success-border: rgba(34, 100, 68, 0.28);
|
||||||
--color-badge-warning-bg: rgba(120, 53, 15, 0.48);
|
--color-badge-warning-bg: rgba(120, 53, 15, 0.22);
|
||||||
--color-badge-warning-fg: #fcd34d;
|
--color-badge-warning-fg: #dfc06a;
|
||||||
--color-badge-warning-border: rgba(180, 83, 9, 0.55);
|
--color-badge-warning-border: rgba(146, 88, 20, 0.28);
|
||||||
--color-badge-danger-bg: rgba(127, 29, 29, 0.42);
|
--color-badge-danger-bg: rgba(127, 29, 29, 0.22);
|
||||||
--color-badge-danger-fg: #fca5a5;
|
--color-badge-danger-fg: #e4a6a6;
|
||||||
--color-badge-danger-border: rgba(185, 28, 28, 0.52);
|
--color-badge-danger-border: rgba(153, 50, 50, 0.28);
|
||||||
|
|
||||||
--color-purpose-consultation-bg: rgba(139, 92, 246, 0.25);
|
--color-purpose-consultation-bg: rgba(139, 92, 246, 0.25);
|
||||||
--color-purpose-consultation-fg: #ddd6fe;
|
--color-purpose-consultation-fg: #ddd6fe;
|
||||||
@@ -254,6 +254,11 @@ body {
|
|||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root[data-theme='dark'] .surface-card,
|
||||||
|
:root:not([data-theme='light']) .surface-card {
|
||||||
|
background: color-mix(in srgb, var(--color-card-background) 82%, var(--color-background-primary));
|
||||||
|
}
|
||||||
|
|
||||||
.surface-panel {
|
.surface-panel {
|
||||||
background: color-mix(in srgb, var(--color-background-secondary) 96%, transparent);
|
background: color-mix(in srgb, var(--color-background-secondary) 96%, transparent);
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
|
|||||||
Reference in New Issue
Block a user