fix: replace window.confirm with inline confirmation for archive project
Swap the browser alert dialog for an in-page confirm/cancel button pair. Shows a loading spinner while the archive request is in flight, then the redirect and toast (from prior commit) handle the rest. Co-Authored-By: Paperclip <noreply@paperclip.ing> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -154,6 +154,71 @@ function ProjectStatusPicker({ status, onChange }: { status: string; onChange: (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ArchiveDangerZone({
|
||||||
|
project,
|
||||||
|
onArchive,
|
||||||
|
archivePending,
|
||||||
|
}: {
|
||||||
|
project: Project;
|
||||||
|
onArchive: (archived: boolean) => void;
|
||||||
|
archivePending?: boolean;
|
||||||
|
}) {
|
||||||
|
const [confirming, setConfirming] = useState(false);
|
||||||
|
const isArchive = !project.archivedAt;
|
||||||
|
const action = isArchive ? "Archive" : "Unarchive";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-3 rounded-md border border-destructive/40 bg-destructive/5 px-4 py-4">
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
{isArchive
|
||||||
|
? "Archive this project to hide it from the sidebar and project selectors."
|
||||||
|
: "Unarchive this project to restore it in the sidebar and project selectors."}
|
||||||
|
</p>
|
||||||
|
{archivePending ? (
|
||||||
|
<Button size="sm" variant="destructive" disabled>
|
||||||
|
<Loader2 className="h-3 w-3 animate-spin mr-1" />
|
||||||
|
{isArchive ? "Archiving..." : "Unarchiving..."}
|
||||||
|
</Button>
|
||||||
|
) : confirming ? (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="text-sm text-destructive font-medium">
|
||||||
|
{action} “{project.name}”?
|
||||||
|
</span>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="destructive"
|
||||||
|
onClick={() => {
|
||||||
|
setConfirming(false);
|
||||||
|
onArchive(isArchive);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => setConfirming(false)}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="destructive"
|
||||||
|
onClick={() => setConfirming(true)}
|
||||||
|
>
|
||||||
|
{isArchive ? (
|
||||||
|
<><Archive className="h-3 w-3 mr-1" />{action} project</>
|
||||||
|
) : (
|
||||||
|
<><ArchiveRestore className="h-3 w-3 mr-1" />{action} project</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSaveState, onArchive, archivePending }: ProjectPropertiesProps) {
|
export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSaveState, onArchive, archivePending }: ProjectPropertiesProps) {
|
||||||
const { selectedCompanyId } = useCompany();
|
const { selectedCompanyId } = useCompany();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
@@ -962,34 +1027,11 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
|
|||||||
<div className="text-xs font-medium text-destructive uppercase tracking-wide">
|
<div className="text-xs font-medium text-destructive uppercase tracking-wide">
|
||||||
Danger Zone
|
Danger Zone
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-3 rounded-md border border-destructive/40 bg-destructive/5 px-4 py-4">
|
<ArchiveDangerZone
|
||||||
<p className="text-sm text-muted-foreground">
|
project={project}
|
||||||
{project.archivedAt
|
onArchive={onArchive}
|
||||||
? "Unarchive this project to restore it in the sidebar and project selectors."
|
archivePending={archivePending}
|
||||||
: "Archive this project to hide it from the sidebar and project selectors."}
|
/>
|
||||||
</p>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="destructive"
|
|
||||||
disabled={archivePending}
|
|
||||||
onClick={() => {
|
|
||||||
const action = project.archivedAt ? "Unarchive" : "Archive";
|
|
||||||
const confirmed = window.confirm(
|
|
||||||
`${action} project "${project.name}"?`,
|
|
||||||
);
|
|
||||||
if (!confirmed) return;
|
|
||||||
onArchive(!project.archivedAt);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{archivePending ? (
|
|
||||||
<><Loader2 className="h-3 w-3 animate-spin mr-1" />{project.archivedAt ? "Unarchiving..." : "Archiving..."}</>
|
|
||||||
) : project.archivedAt ? (
|
|
||||||
<><ArchiveRestore className="h-3 w-3 mr-1" />Unarchive project</>
|
|
||||||
) : (
|
|
||||||
<><Archive className="h-3 w-3 mr-1" />Archive project</>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user