11import { useQueryClient } from '@tanstack/react-query' ;
22import CheckCircle from 'lucide-react/icons/check-circle' ;
3+ import ChevronDown from 'lucide-react/icons/chevron-down' ;
34import Cloud from 'lucide-react/icons/cloud' ;
45import Info from 'lucide-react/icons/info' ;
56import Loader2 from 'lucide-react/icons/loader-2' ;
@@ -53,6 +54,8 @@ export const AccountModal = ({ account, onClose, preloadedConfig }: AccountModal
5354 const [ serverType , setServerType ] = useState < ServerType > (
5455 ( ) => preloadedConfig ?. serverType || account ?. serverType || 'generic' ,
5556 ) ;
57+ const [ calendarHomeUrl , setCalendarHomeUrl ] = useState ( ( ) => account ?. calendarHomeUrl || '' ) ;
58+ const [ showAdvanced , setShowAdvanced ] = useState ( ( ) => ! ! account ?. calendarHomeUrl ) ;
5659 const [ isLoading , setIsLoading ] = useState ( false ) ;
5760 const [ isTesting , setIsTesting ] = useState ( false ) ;
5861 const [ testSuccess , setTestSuccess ] = useState ( false ) ;
@@ -68,13 +71,19 @@ export const AccountModal = ({ account, onClose, preloadedConfig }: AccountModal
6871 useModalEscapeKey ( onClose ) ;
6972
7073 // Reset test state when credentials change
71- const [ prevCredentials , setPrevCredentials ] = useState ( { serverUrl, username, password } ) ;
74+ const [ prevCredentials , setPrevCredentials ] = useState ( {
75+ serverUrl,
76+ username,
77+ password,
78+ calendarHomeUrl,
79+ } ) ;
7280 if (
7381 serverUrl !== prevCredentials . serverUrl ||
7482 username !== prevCredentials . username ||
75- password !== prevCredentials . password
83+ password !== prevCredentials . password ||
84+ calendarHomeUrl !== prevCredentials . calendarHomeUrl
7685 ) {
77- setPrevCredentials ( { serverUrl, username, password } ) ;
86+ setPrevCredentials ( { serverUrl, username, password, calendarHomeUrl } ) ;
7887 if ( testSuccess || testedConnectionId ) {
7988 setTestSuccess ( false ) ;
8089 setTestedConnectionId ( null ) ;
@@ -178,6 +187,7 @@ export const AccountModal = ({ account, onClose, preloadedConfig }: AccountModal
178187 username ,
179188 effectivePassword ,
180189 serverType ,
190+ calendarHomeUrl . trim ( ) || undefined ,
181191 ) ;
182192
183193 // Check if this is a Vikunja server and warn the user
@@ -231,6 +241,7 @@ export const AccountModal = ({ account, onClose, preloadedConfig }: AccountModal
231241 username ,
232242 effectivePassword ,
233243 serverType ,
244+ calendarHomeUrl . trim ( ) || undefined ,
234245 ) ;
235246 }
236247
@@ -242,6 +253,7 @@ export const AccountModal = ({ account, onClose, preloadedConfig }: AccountModal
242253 username,
243254 password : effectivePassword || account . password ,
244255 serverType,
256+ calendarHomeUrl : calendarHomeUrl . trim ( ) || undefined ,
245257 } ,
246258 } ) ;
247259 } else {
@@ -269,6 +281,7 @@ export const AccountModal = ({ account, onClose, preloadedConfig }: AccountModal
269281 username ,
270282 effectivePassword ,
271283 serverType ,
284+ calendarHomeUrl . trim ( ) || undefined ,
272285 ) ;
273286
274287 // Check if this is a Vikunja server and warn the user
@@ -297,6 +310,7 @@ export const AccountModal = ({ account, onClose, preloadedConfig }: AccountModal
297310 username,
298311 password : effectivePassword ,
299312 serverType,
313+ calendarHomeUrl : calendarHomeUrl . trim ( ) || undefined ,
300314 } ,
301315 {
302316 onSuccess : async ( newAccount ) => {
@@ -377,7 +391,11 @@ export const AccountModal = ({ account, onClose, preloadedConfig }: AccountModal
377391 </ button >
378392 </ div >
379393
380- < form onSubmit = { handleSubmit } className = "p-4 space-y-4" >
394+ < form
395+ onSubmit = { handleSubmit }
396+ className = "flex flex-col min-h-0 max-h-[calc(90vh-4rem)]"
397+ >
398+ < div className = "p-4 space-y-4 overflow-y-auto flex-1 min-h-0" >
381399 < div >
382400 < label
383401 htmlFor = "account-name"
@@ -494,6 +512,43 @@ export const AccountModal = ({ account, onClose, preloadedConfig }: AccountModal
494512 />
495513 </ div >
496514
515+ < div >
516+ < button
517+ type = "button"
518+ onClick = { ( ) => setShowAdvanced ( ( v ) => ! v ) }
519+ className = "flex items-center gap-1 text-xs text-surface-500 dark:text-surface-400 hover:text-surface-700 dark:hover:text-surface-200 transition-colors outline-none focus-visible:ring-2 focus-visible:ring-primary-500 rounded"
520+ >
521+ < ChevronDown
522+ className = { `w-3.5 h-3.5 transition-transform ${ showAdvanced ? '' : '-rotate-90' } ` }
523+ />
524+ Advanced
525+ </ button >
526+ { showAdvanced && (
527+ < div className = "mt-3 space-y-3" >
528+ < div >
529+ < label
530+ htmlFor = "calendar-home-url"
531+ className = "block text-sm font-medium text-surface-700 dark:text-surface-300 mb-1"
532+ >
533+ Calendar Home URL
534+ </ label >
535+ < ComposedInput
536+ id = "calendar-home-url"
537+ type = "url"
538+ value = { calendarHomeUrl }
539+ onChange = { setCalendarHomeUrl }
540+ placeholder = "https://caldav.example.com/calendars/user/"
541+ className = "w-full px-3 py-2 text-sm text-surface-800 dark:text-surface-200 bg-surface-100 dark:bg-surface-700 border border-transparent rounded-lg focus:outline-none focus:border-primary-300 dark:focus:border-primary-400 focus:bg-white dark:focus:bg-primary-900/30 transition-colors"
542+ />
543+ < p className = "mt-1.5 text-xs flex flex-row text-surface-500 dark:text-surface-400" >
544+ < Info className = "inline w-3.5 h-3.5 mr-1 shrink-0 text-surface-400" />
545+ Use this if auto-discovery is not possible.
546+ </ p >
547+ </ div >
548+ </ div >
549+ ) }
550+ </ div >
551+
497552 { error && (
498553 < div className = "p-3 text-sm text-red-600 dark:text-red-400 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg" >
499554 { error }
@@ -560,7 +615,9 @@ export const AccountModal = ({ account, onClose, preloadedConfig }: AccountModal
560615 </ div >
561616 ) }
562617
563- < div className = "flex justify-between gap-3 pt-2" >
618+ </ div >
619+
620+ < div className = "flex justify-between gap-3 p-4 pt-3 border-t border-surface-200 dark:border-surface-700 shrink-0" >
564621 < button
565622 type = "button"
566623 onClick = { handleTestConnection }
0 commit comments