@@ -4,20 +4,18 @@ import { Box, Button, CircularProgress, FormControl, InputLabel, MenuItem, Selec
44import { ErrorBoundary , Suspense } from "@suspensive/react" ;
55import * as React from "react" ;
66
7+ import { Fieldset } from "./fieldset" ;
78import { useAppContext } from "../../contexts/app_context" ;
89import { PublicFileUploadDialog } from "../dialogs/public_file_upload" ;
9- import { Fieldset } from "./fieldset" ;
1010
11- type PublicFileSelectorProps = SelectProps < string | null | undefined > & {
12- setFileIdAsValue ?: ( fileId ?: string | null ) => void ;
13- } ;
11+ type PublicFileSelectorProps = Omit < SelectProps < string | null > , "inputRef" > ;
1412
1513const ImageFallback : React . FC < { language : "ko" | "en" } > = ( { language } ) => (
1614 < Box children = { language === "ko" ? "이미지가 없습니다." : "No image available." } />
1715) ;
1816
1917type PublicFileSelectorState = {
20- fileId ?: string | null ;
18+ value ?: string | null ;
2119 openUploadDialog ?: boolean ;
2220} ;
2321
@@ -29,35 +27,48 @@ const ScaledFallbackImage = styled(Common.Components.FallbackImage)({
2927
3028export const PublicFileSelector : React . FC < PublicFileSelectorProps > = ErrorBoundary . with (
3129 { fallback : Common . Components . ErrorFallback } ,
32- Suspense . with ( { fallback : < CircularProgress /> } , ( { onChange, setFileIdAsValue, ...props } ) => {
33- const [ selectorState , setSelectorState ] = React . useState < PublicFileSelectorState > ( { } ) ;
30+ Suspense . with ( { fallback : < CircularProgress /> } , ( { value, onChange, ...props } ) => {
31+ const selectInputRef = React . useRef < HTMLSelectElement | null > ( null ) ;
32+ const [ selectorState , setSelectorState ] = React . useState < PublicFileSelectorState > ( { value } ) ;
3433 const { language } = useAppContext ( ) ;
3534 const participantPortalClient = Common . Hooks . BackendParticipantPortalAPI . useParticipantPortalClient ( ) ;
3635 const { data } = Common . Hooks . BackendParticipantPortalAPI . usePublicFilesQuery ( participantPortalClient ) ;
3736 const isMobile = useMediaQuery ( ( theme ) => theme . breakpoints . down ( "md" ) ) ;
3837
39- const setSelectedFile : SelectProps < string | null | undefined > [ "onChange" ] = ( event , child ) => {
40- setSelectorState ( ( ps ) => ( { ...ps , fileId : event . target . value } ) ) ;
38+ const setSelectedFile : SelectProps < string | null > [ "onChange" ] = ( event , child ) => {
39+ setSelectorState ( ( ps ) => ( { ...ps , value : event . target . value } ) ) ;
4140 onChange ?.( event , child ) ;
4241 } ;
42+ const setSelectInputValue = ( value : string | null ) => {
43+ if ( selectInputRef . current ) selectInputRef . current . value = value || "" ;
44+
45+ setSelectorState ( ( ps ) => ( { ...ps , value } ) ) ;
46+ onChange ?.( { target : { value } } as React . ChangeEvent < HTMLSelectElement & HTMLInputElement > , null ) ;
47+ } ;
4348 const openUploadDialog = ( ) => setSelectorState ( ( ps ) => ( { ...ps , openUploadDialog : true } ) ) ;
4449 const closeUploadDialog = ( ) => setSelectorState ( ( ps ) => ( { ...ps , openUploadDialog : false } ) ) ;
4550
4651 const emptyValueStr = language === "ko" ? "선택 안 함" : "Not selected" ;
4752 const uploadStr = language === "ko" ? "파일 업로드" : "Upload File" ;
48- const files = [ ...( props . required ? [ ] : [ { id : undefined , file : emptyValueStr , name : emptyValueStr } ] ) , ...data ] ;
49- const selectedFile = data . find ( ( file ) => file . id === props . value ) ;
53+ const files = [ ...( props . required ? [ ] : [ { id : "" , file : emptyValueStr , name : emptyValueStr } ] ) , ...data ] ;
54+ const selectedFile = data . find ( ( file ) => file . id === ( selectorState . value || "" ) ) ;
5055
5156 return (
5257 < >
53- < PublicFileUploadDialog open = { ! ! selectorState . openUploadDialog } onClose = { closeUploadDialog } setFileIdAsValue = { setFileIdAsValue } />
58+ < PublicFileUploadDialog open = { ! ! selectorState . openUploadDialog } onClose = { closeUploadDialog } setFileIdAsValue = { setSelectInputValue } />
5459 < Fieldset legend = { props . label ?. toString ( ) || "" } >
5560 < Stack direction = "column" spacing = { 2 } alignItems = "center" justifyContent = "center" >
56- < ScaledFallbackImage src = { selectedFile ?. file } alt = "Selected File" loading = "lazy" errorFallback = { < ImageFallback language = { language } /> } />
61+ < ScaledFallbackImage
62+ key = { selectedFile ?. file || "" }
63+ src = { selectedFile ?. file }
64+ alt = "Selected File"
65+ loading = "lazy"
66+ errorFallback = { < ImageFallback language = { language } /> }
67+ />
5768 < Stack direction = { isMobile ? "column" : "row" } spacing = { 2 } sx = { { width : "100%" } } alignItems = "center" >
5869 < FormControl fullWidth >
5970 < InputLabel id = "public-file-label" > { props . label } </ InputLabel >
60- < Select labelId = "public-file-label" onChange = { setSelectedFile } { ...props } >
71+ < Select labelId = "public-file-label" ref = { selectInputRef } value = { selectorState . value || "" } onChange = { setSelectedFile } { ...props } >
6172 { files . map ( ( file ) => (
6273 < MenuItem key = { file . id } value = { file . id } children = { file . name } />
6374 ) ) }
0 commit comments