@traky-app/ui 1.6.4 → 1.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,6 +5,8 @@ import { IconEdit, IconMapPin, IconPlus } from "@tabler/icons-react"
5
5
  import type { Icon } from "@tabler/icons-react"
6
6
 
7
7
  import { cn } from "../lib/utils"
8
+ import { fetchStates } from "../lib/geo-locations"
9
+ import { googleMapsSelectionToFormPatch } from "../lib/google-maps-address"
8
10
  import {
9
11
  AlertDialog,
10
12
  AlertDialogAction,
@@ -14,7 +16,7 @@ import {
14
16
  } from "./alert-dialog"
15
17
  import { Button } from "./button"
16
18
  import { Spinner } from "./spinner"
17
- import { googleMapsSelectionToFormPatch } from "../lib/google-maps-address"
19
+ import { StateSelect } from "./state-select"
18
20
  import {
19
21
  Card,
20
22
  CardContent,
@@ -24,6 +26,8 @@ import {
24
26
  CardTitle,
25
27
  } from "./card"
26
28
  import { EntityIcon } from "./entity-icon"
29
+ import { CitySelect } from "./city-select"
30
+ import { CountrySelect } from "./country-select"
27
31
  import { GoogleMapsAddressPicker } from "./google-maps-address-picker"
28
32
  import { Input } from "./input"
29
33
  import { Label } from "./label"
@@ -81,17 +85,6 @@ function OfficeAddressEntryModeSwitch({
81
85
  /** `customer` = dirección de envío (contacto/portal). `enterprise` = sucursal o bodega. */
82
86
  export type OfficeAddressFormVariant = "customer" | "enterprise"
83
87
 
84
- const OFFICE_ADDRESS_COUNTRY_OPTIONS: { code: string; label: string }[] = [
85
- { code: "EC", label: "Ecuador" },
86
- { code: "US", label: "Estados Unidos" },
87
- { code: "MX", label: "México" },
88
- { code: "CO", label: "Colombia" },
89
- { code: "PE", label: "Perú" },
90
- { code: "CL", label: "Chile" },
91
- { code: "PA", label: "Panamá" },
92
- { code: "CR", label: "Costa Rica" },
93
- ]
94
-
95
88
  const FAX_COUNTRY_CODES = new Set(["US", "CA", "PR"])
96
89
 
97
90
  export function isOfficeAddressFaxCountry(countryCode: string | undefined) {
@@ -276,29 +269,51 @@ export function OfficeAddressFormCard({
276
269
  }
277
270
 
278
271
  const embedded = layout === "dialog"
272
+ const countryCode = form.countryCode?.trim().toUpperCase() ?? ""
273
+ const [stateCode, setStateCode] = React.useState("")
274
+
275
+ React.useEffect(() => {
276
+ const stateName = form.stateOrProvince?.trim() ?? ""
277
+ if (!countryCode || !stateName) {
278
+ setStateCode("")
279
+ return
280
+ }
281
+
282
+ let cancelled = false
283
+ void fetchStates(countryCode).then((list) => {
284
+ if (cancelled) return
285
+ const wanted = stateName.toLowerCase()
286
+ const match = list.find(
287
+ (item) =>
288
+ item.name.toLowerCase() === wanted ||
289
+ item.code.toLowerCase() === wanted,
290
+ )
291
+ setStateCode(match?.code ?? "")
292
+ })
293
+
294
+ return () => {
295
+ cancelled = true
296
+ }
297
+ }, [countryCode, form.stateOrProvince])
279
298
 
280
299
  const countryControl =
281
300
  countryField ?? (
282
- <Select
283
- value={form.countryCode || undefined}
301
+ <CountrySelect
302
+ className="w-full"
303
+ size="lg"
304
+ value={form.countryCode}
284
305
  disabled={busy}
285
- onValueChange={(code) =>
286
- onFormChange((prev) => ({ ...prev, countryCode: code }))
287
- }
288
- >
289
- <SelectTrigger className="w-full" aria-label="País">
290
- <SelectValue placeholder="Selecciona el país" />
291
- </SelectTrigger>
292
- <SelectContent>
293
- <SelectGroup>
294
- {OFFICE_ADDRESS_COUNTRY_OPTIONS.map((c) => (
295
- <SelectItem key={c.code} value={c.code}>
296
- {c.label}
297
- </SelectItem>
298
- ))}
299
- </SelectGroup>
300
- </SelectContent>
301
- </Select>
306
+ searchPlaceholder="Escribe el país…"
307
+ onChange={(country) => {
308
+ setStateCode("")
309
+ onFormChange((prev) => ({
310
+ ...prev,
311
+ countryCode: country.code,
312
+ stateOrProvince: "",
313
+ city: "",
314
+ }))
315
+ }}
316
+ />
302
317
  )
303
318
 
304
319
  return (
@@ -402,23 +417,45 @@ export function OfficeAddressFormCard({
402
417
  />
403
418
  </div>
404
419
  <div className="space-y-1">
405
- <Label htmlFor="office-city">Ciudad</Label>
406
- <Input
407
- id="office-city"
408
- name="city"
409
- value={form.city}
410
- onChange={handleChange}
420
+ <Label htmlFor="office-state">
421
+ Estado / Región / Municipio
422
+ </Label>
423
+ <StateSelect
424
+ id="office-state"
425
+ className="w-full"
426
+ countryCode={countryCode}
427
+ value={form.stateOrProvince}
411
428
  disabled={busy}
429
+ onChange={(option) => {
430
+ setStateCode(option?.code ?? "")
431
+ onFormChange((prev) => ({
432
+ ...prev,
433
+ stateOrProvince: option?.name ?? "",
434
+ city: "",
435
+ }))
436
+ }}
412
437
  />
413
438
  </div>
414
439
  <div className="space-y-1">
415
- <Label htmlFor="office-state">Estado / Provincia</Label>
416
- <Input
417
- id="office-state"
418
- name="stateOrProvince"
419
- value={form.stateOrProvince}
420
- onChange={handleChange}
440
+ <Label htmlFor="office-city">
441
+ Ciudad / Pueblo / Distrito
442
+ </Label>
443
+ <CitySelect
444
+ id="office-city"
445
+ className="w-full"
446
+ countryCode={countryCode}
447
+ stateCode={stateCode}
448
+ value={form.city}
421
449
  disabled={busy}
450
+ onChange={(option) => {
451
+ onFormChange((prev) => ({
452
+ ...prev,
453
+ city: option?.name ?? "",
454
+ ...(option?.stateName
455
+ ? { stateOrProvince: option.stateName }
456
+ : {}),
457
+ }))
458
+ }}
422
459
  />
423
460
  </div>
424
461
  <div className="space-y-1">