11'use client'
22
3- import { useId , useState } from 'react'
3+ import { useId , useRef , useState } from 'react'
44import {
55 Checkbox ,
66 ChipConfirmModal ,
@@ -20,7 +20,7 @@ import { useParams } from 'next/navigation'
2020import type { ColumnDefinition , TableInfo , TableRow } from '@/lib/table'
2121import { columnTypeOf } from '@/lib/table/column-types'
2222import { resolveCurrencyCode } from '@/lib/table/currency'
23- import { useTimezone } from '@/hooks/queries/general-settings'
23+ import { useTimezoneState } from '@/hooks/queries/general-settings'
2424import { useDeleteTableRow , useDeleteTableRows , useUpdateTableRow } from '@/hooks/queries/tables'
2525import {
2626 cleanCellValue ,
@@ -78,7 +78,14 @@ export function RowModal({ mode, isOpen, onClose, table, row, rowIds, onSuccess
7878 const schema = table ?. schema
7979 const columns = schema ?. columns || [ ]
8080
81- const timeZone = useTimezone ( )
81+ const timezoneState = useTimezoneState ( )
82+ const editTimeZoneRef = useRef < string | null > ( null )
83+ if ( timezoneState . status === 'ready' && editTimeZoneRef . current === null ) {
84+ editTimeZoneRef . current = timezoneState . timezone
85+ }
86+ const hasTtlColumn = mode === 'edit' && columns . some ( ( column ) => column . type === 'ttl' )
87+ const ttlTimezoneUnavailable = hasTtlColumn && editTimeZoneRef . current === null
88+ const timeZone = editTimeZoneRef . current ?? timezoneState . timezone
8289 const [ rowData , setRowData ] = useState < Record < string , unknown > > ( ( ) =>
8390 mode === 'edit' && row ? row . data : { }
8491 )
@@ -92,6 +99,7 @@ export function RowModal({ mode, isOpen, onClose, table, row, rowIds, onSuccess
9299 const handleFormSubmit = async ( e ?: React . FormEvent ) => {
93100 e ?. preventDefault ( )
94101 setError ( null )
102+ if ( ttlTimezoneUnavailable ) return
95103
96104 try {
97105 const cleanData = cleanRowData ( columns , rowData , timeZone )
@@ -169,15 +177,22 @@ export function RowModal({ mode, isOpen, onClose, table, row, rowIds, onSuccess
169177 Update values for { table ?. name ?? 'table' }
170178 </ p >
171179 < form onSubmit = { handleFormSubmit } className = 'contents' >
172- < button type = 'submit' hidden disabled = { isSubmitting } />
173- { columns . map ( ( column ) => (
174- < ColumnField
175- key = { column . name }
176- column = { column }
177- value = { rowData [ column . name ] }
178- onChange = { ( value ) => setRowData ( ( prev ) => ( { ...prev , [ column . name ] : value } ) ) }
179- />
180- ) ) }
180+ < button type = 'submit' hidden disabled = { isSubmitting || ttlTimezoneUnavailable } />
181+ { ttlTimezoneUnavailable ? (
182+ < p role = 'status' className = 'px-2 text-[var(--text-muted)] text-small' >
183+ { timezoneState . status === 'error' ? 'Timezone unavailable' : 'Loading timezone…' }
184+ </ p >
185+ ) : (
186+ columns . map ( ( column ) => (
187+ < ColumnField
188+ key = { column . name }
189+ column = { column }
190+ value = { rowData [ column . name ] }
191+ timeZone = { timeZone }
192+ onChange = { ( value ) => setRowData ( ( prev ) => ( { ...prev , [ column . name ] : value } ) ) }
193+ />
194+ ) )
195+ ) }
181196 </ form >
182197 < ChipModalError > { error } </ ChipModalError >
183198 </ ChipModalBody >
@@ -187,7 +202,7 @@ export function RowModal({ mode, isOpen, onClose, table, row, rowIds, onSuccess
187202 primaryAction = { {
188203 label : isSubmitting ? 'Updating...' : 'Update Row' ,
189204 onClick : ( ) => handleFormSubmit ( ) ,
190- disabled : isSubmitting ,
205+ disabled : isSubmitting || ttlTimezoneUnavailable ,
191206 } }
192207 />
193208 </ ChipModal >
@@ -197,12 +212,12 @@ export function RowModal({ mode, isOpen, onClose, table, row, rowIds, onSuccess
197212interface ColumnFieldProps {
198213 column : ColumnDefinition
199214 value : unknown
215+ timeZone : string
200216 onChange : ( value : unknown ) => void
201217}
202218
203- function ColumnField ( { column, value, onChange } : ColumnFieldProps ) {
219+ function ColumnField ( { column, value, timeZone , onChange } : ColumnFieldProps ) {
204220 const checkboxId = useId ( )
205- const timeZone = useTimezone ( )
206221 const title = (
207222 < >
208223 { column . name }
@@ -261,22 +276,22 @@ function ColumnField({ column, value, onChange }: ColumnFieldProps) {
261276
262277 if ( definition . editor === 'date' ) {
263278 const parts = dateValueToLocalParts ( formatValueForInput ( value , column . type , timeZone ) )
279+ const valueFromParts = ( day : string , time : string | null ) =>
280+ column . type === 'ttl' && time ? `${ day } T${ time } ` : localPartsToDateValue ( day , time , timeZone )
264281 return (
265282 < ChipModalField type = 'custom' title = { title } required = { column . required } hint = { hint } >
266283 < div className = 'flex items-center gap-2' >
267284 < ChipDatePicker
268285 value = { parts . day ?? undefined }
269286 today = { todayLocalCalendarDate ( timeZone ) }
270- onChange = { ( day ) => onChange ( localPartsToDateValue ( day , parts . time , timeZone ) ) }
287+ onChange = { ( day ) => onChange ( valueFromParts ( day , parts . time ) ) }
271288 placeholder = 'Select date'
272289 className = 'flex-1'
273290 />
274291 < ChipTimePicker
275292 value = { parts . time ?. slice ( 0 , 5 ) }
276293 onChange = { ( time ) =>
277- onChange (
278- localPartsToDateValue ( parts . day ?? todayLocalCalendarDate ( timeZone ) , time , timeZone )
279- )
294+ onChange ( valueFromParts ( parts . day ?? todayLocalCalendarDate ( timeZone ) , time ) )
280295 }
281296 placeholder = 'Add time'
282297 className = 'w-[110px]'
0 commit comments