fix(calendar): show in-flight state on Save and surface the silent length-guard rejection

This commit is contained in:
Tex LH Chi
2026-09-18 17:43:21 +08:00
committed by texchi2
parent 5de98bc04b
commit e9a72ec17e
+11 -2
View File
@@ -2,6 +2,7 @@
import { useState, useEffect, useCallback, useRef, useMemo } from "react";
import { useTranslations, useLocale } from "next-intl";
import { toast } from "@/stores/toast-store";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { LinkifiedText } from "@/components/ui/linkified-text";
@@ -493,7 +494,13 @@ export function EventModal({
const handleSave = useCallback(async () => {
const trimmedTitle = title.trim();
if (!trimmedTitle || isSaving) return;
if (trimmedTitle.length > 500 || description.trim().length > 10000 || location.trim().length > 500) return;
if (trimmedTitle.length > 500 || description.trim().length > 10000 || location.trim().length > 500) {
// This guard returned silently, so a rejected save was indistinguishable from a dead
// button. The fields also enforce their limits via maxLength, so this is a backstop —
// but if it ever fires, say so.
toast.error(t("notifications.event_error"));
return;
}
const pendingAttendee = participantInputRef.current?.flush() ?? null;
const effectiveAttendees = pendingAttendee ? [...attendees, pendingAttendee] : attendees;
@@ -1436,7 +1443,9 @@ export function EventModal({
disabled={!title.trim() || isSaving}
className="w-full"
>
{t("form.save")}
{/* While a save is in flight the button was disabled with no visible change, so a
slow request (mobile, VPN) looked like a dead button for the whole timeout. */}
{isSaving ? t("form.saving") : t("form.save")}
</Button>
</div>
)}