feat(forms): country→timezone autoset, "Other" channel hint, polish
Client form: when nationality is picked and timezone empty, primary IANA zone for the country is pre-filled (skips when user has chosen a zone explicitly). When a contact's preferred channel is `'other'`, the inline `Label` field flips to "Specify" / "e.g. Telegram, Signal" so the rep records what the channel actually is. Yacht form: replace the free-text 2-letter flag input with the shared `CountryCombobox` so flags stay valid ISO codes. User settings: timezone pre-populates from `Intl.DateTimeFormat().resolvedOptions().timeZone` on first load (was empty before); country change auto-fills timezone with the same helper as the client form. Phone field upgraded to the shared `<PhoneInput>` (country-flag dropdown + AsYouType formatter) seeded from the page's country state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,7 @@ import { DedupSuggestionPanel } from '@/components/clients/dedup-suggestion-pane
|
||||
import { apiFetch } from '@/lib/api/client';
|
||||
import { createClientSchema, type CreateClientInput } from '@/lib/validators/clients';
|
||||
import type { CountryCode } from '@/lib/i18n/countries';
|
||||
import { primaryTimezoneFor } from '@/lib/i18n/timezones';
|
||||
|
||||
interface ClientFormProps {
|
||||
open: boolean;
|
||||
@@ -84,6 +85,17 @@ export function ClientForm({ open, onOpenChange, client, onUseExistingClient }:
|
||||
const { fields, append, remove } = useFieldArray({ control, name: 'contacts' });
|
||||
const tagIds = watch('tagIds') ?? [];
|
||||
|
||||
// When the rep picks a country and no timezone is set yet, pre-fill the
|
||||
// timezone with the country's primary IANA zone. Skips when the user has
|
||||
// already chosen a zone explicitly so we never clobber a deliberate pick.
|
||||
const watchedNationality = watch('nationalityIso');
|
||||
const watchedTimezone = watch('timezone');
|
||||
useEffect(() => {
|
||||
if (!watchedNationality || watchedTimezone) return;
|
||||
const primary = primaryTimezoneFor(watchedNationality as CountryCode);
|
||||
if (primary) setValue('timezone', primary);
|
||||
}, [watchedNationality, watchedTimezone, setValue]);
|
||||
|
||||
// Populate form when editing
|
||||
useEffect(() => {
|
||||
if (client && open) {
|
||||
@@ -287,11 +299,17 @@ export function ClientForm({ open, onOpenChange, client, onUseExistingClient }:
|
||||
</div>
|
||||
|
||||
<div className="col-span-2 space-y-1">
|
||||
<Label className="text-xs">Label</Label>
|
||||
<Label className="text-xs">
|
||||
{watch(`contacts.${index}.channel`) === 'other' ? 'Specify' : 'Label'}
|
||||
</Label>
|
||||
<Input
|
||||
{...register(`contacts.${index}.label`)}
|
||||
className="h-8"
|
||||
placeholder="work"
|
||||
placeholder={
|
||||
watch(`contacts.${index}.channel`) === 'other'
|
||||
? 'e.g. Telegram, Signal'
|
||||
: 'work'
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user