@@ -190,6 +190,7 @@ export function PersonDetail() {
190190 const [ showUploadDialog , setShowUploadDialog ] = useState ( false ) ;
191191 const [ showAncestryUploadDialog , setShowAncestryUploadDialog ] = useState ( false ) ;
192192 const [ showRelationshipModal , setShowRelationshipModal ] = useState ( false ) ;
193+ const [ hintsProcessing , setHintsProcessing ] = useState ( false ) ;
193194
194195 // Local overrides state
195196 const [ overrides , setOverrides ] = useState < PersonOverrides | null > ( null ) ;
@@ -495,6 +496,36 @@ export function PersonDetail() {
495496 setSyncLoading ( false ) ;
496497 } ;
497498
499+ const handleProcessAncestryHints = async ( ) => {
500+ if ( ! dbId || ! personId ) return ;
501+
502+ setHintsProcessing ( true ) ;
503+
504+ const result = await api . processAncestryHints ( dbId , personId ) . catch ( err => {
505+ toast . error ( `Failed to process hints: ${ err . message } ` ) ;
506+ return null ;
507+ } ) ;
508+
509+ if ( result ) {
510+ if ( result . hintsProcessed > 0 ) {
511+ toast . success ( `Processed ${ result . hintsProcessed } free hints on Ancestry` ) ;
512+ // Refresh data from Ancestry after processing hints
513+ await handleRefreshProvider ( 'ancestry' ) ;
514+ } else if ( result . hintsFound === 0 ) {
515+ toast ( 'No free hints available' , { icon : 'ℹ️' } ) ;
516+ } else if ( result . errors . length > 0 ) {
517+ toast . error ( `Hints processing failed: ${ result . errors [ 0 ] } ` ) ;
518+ }
519+ }
520+
521+ setHintsProcessing ( false ) ;
522+ } ;
523+
524+ const handleRefreshProvider = async ( provider : 'ancestry' | 'wikitree' | 'familysearch' ) => {
525+ if ( ! dbId || ! personId ) return ;
526+ await api . refreshFromProvider ( dbId , personId , provider ) . catch ( ( ) => null ) ;
527+ } ;
528+
498529 // =============================================================================
499530 // LOCAL OVERRIDE HANDLERS
500531 // =============================================================================
@@ -596,6 +627,15 @@ export function PersonDetail() {
596627 toast . success ( 'Deleted' ) ;
597628 } , [ dbId , personId , refreshOverrides ] ) ;
598629
630+ // Called when a field value is applied from provider data (e.g., "Use" button)
631+ const handleFieldApplied = useCallback ( async ( ) => {
632+ await refreshOverrides ( ) ;
633+ // Refresh person data to show the new value in the SparseTree row
634+ if ( ! dbId || ! personId ) return ;
635+ const newPerson = await api . getPerson ( dbId , personId ) ;
636+ if ( newPerson ) setPerson ( newPerson ) ;
637+ } , [ dbId , personId , refreshOverrides ] ) ;
638+
599639 // =============================================================================
600640 // HELPER FUNCTIONS FOR OVERRIDES
601641 // =============================================================================
@@ -1159,10 +1199,12 @@ export function PersonDetail() {
11591199 onShowAncestryUploadDialog = { ( ) => setShowAncestryUploadDialog ( true ) }
11601200 onShowLinkInput = { ( platform ) => setLinkingPlatform ( platform ) }
11611201 onPhotoChanged = { refreshPhotoState }
1162- onFieldChanged = { refreshOverrides }
1202+ onFieldChanged = { handleFieldApplied }
1203+ onProcessAncestryHints = { handleProcessAncestryHints }
11631204 syncLoading = { syncLoading }
11641205 scrapeLoading = { scrapeLoading }
11651206 fetchingPhotoFrom = { fetchingPhotoFrom }
1207+ hintsProcessing = { hintsProcessing }
11661208 />
11671209
11681210 { /* Lineage path - compact */ }
@@ -1198,6 +1240,11 @@ export function PersonDetail() {
11981240 dbId = { dbId }
11991241 personId = { personId }
12001242 onClose = { ( ) => setShowUploadDialog ( false ) }
1243+ onPhotoSynced = { ( ) => {
1244+ // Photo was uploaded and synced to local cache - update UI without re-downloading
1245+ setHasFsPhoto ( true ) ;
1246+ setPhotoVersion ( Date . now ( ) ) ; // Bust browser cache to show the photo
1247+ } }
12011248 />
12021249 ) }
12031250
0 commit comments