66 EditableInput ,
77 EditablePreview ,
88 Flex ,
9+ FormControl ,
910 IconButton ,
1011 Input ,
1112 Switch ,
@@ -14,8 +15,10 @@ import {
1415 useEditableControls ,
1516 useToast ,
1617} from "@chakra-ui/react" ;
17- import { Assignment , Location } from "@prisma/client" ;
18+
19+ import { Assignment , Category , Location } from "@prisma/client" ;
1820import { UseTRPCMutationResult } from "@trpc/react/shared" ;
21+ import { MultiValue , Select , SingleValue } from "chakra-react-select" ;
1922import { useState } from "react" ;
2023import { FaEye , FaEyeSlash } from "react-icons/fa" ;
2124import { DARK_GRAY_COLOR } from "../../utils/constants" ;
@@ -73,15 +76,47 @@ const AdminCard = (props: AdminCardProps) => {
7376 const [ isPriority , setIsPriority ] = useState (
7477 isAssignment ? ( assignmentOrLocation as Assignment ) . isPriority : false ,
7578 ) ;
79+ const [ assignmentCategoryId , setAssignmentCategoryId ] = useState (
80+ isAssignment ? ( assignmentOrLocation as Assignment ) . categoryId : undefined ,
81+ ) ;
82+ const [ locationCategoryIds , setLocationCategoryIds ] = useState < number [ ] > ( ) ;
83+ const [ allCategories , setAllCategories ] = useState < Category [ ] > ( ) ;
84+
7685 const context = trpc . useContext ( ) ;
7786 const toast = useToast ( ) ;
7887
88+ trpc . admin . getCategoriesForLocation . useQuery (
89+ {
90+ locationId : isAssignment
91+ ? undefined
92+ : ( assignmentOrLocation as Location ) . id ,
93+ } ,
94+ {
95+ refetchOnWindowFocus : false ,
96+ onSuccess : ( data ) => {
97+ setLocationCategoryIds ( data ?. categories . map ( ( category ) => category . id ) ) ;
98+ } ,
99+ enabled : ! isAssignment ,
100+ } ,
101+ ) ;
102+
103+ trpc . admin . getAllCategories . useQuery ( undefined , {
104+ refetchOnWindowFocus : false ,
105+ onSuccess : ( data ) => {
106+ setAllCategories ( data ) ;
107+ } ,
108+ } ) ;
109+
79110 const handleNameChange = async ( newName : string ) => {
80111 await editMutation . mutateAsync ( {
81112 id : assignmentOrLocation . id ,
82113 name : newName ,
83114 isActive : assignmentOrLocation . isActive ,
84115 isHidden : assignmentOrLocation . isHidden ,
116+ categoryId : isAssignment
117+ ? ( assignmentOrLocation as Assignment ) . categoryId
118+ : undefined ,
119+ categoryIds : isAssignment ? undefined : locationCategoryIds ,
85120 } ) ;
86121 } ;
87122
@@ -93,6 +128,10 @@ const AdminCard = (props: AdminCardProps) => {
93128 isActive : assignmentOrLocation . isActive ,
94129 isHidden : assignmentOrLocation . isHidden ,
95130 isPriority : newPriority ,
131+ categoryId : isAssignment
132+ ? ( assignmentOrLocation as Assignment ) . categoryId
133+ : undefined ,
134+ categoryIds : isAssignment ? undefined : locationCategoryIds ,
96135 } ) ;
97136 } ;
98137
@@ -105,6 +144,10 @@ const AdminCard = (props: AdminCardProps) => {
105144 name : assignmentOrLocation . name ,
106145 isActive : newActive ,
107146 isHidden : newActive ? false : isHidden ,
147+ categoryId : isAssignment
148+ ? ( assignmentOrLocation as Assignment ) . categoryId
149+ : undefined ,
150+ categoryIds : isAssignment ? undefined : locationCategoryIds ,
108151 } )
109152 . then ( ( ) => {
110153 context . admin . getAllLocations . invalidate ( ) ;
@@ -130,6 +173,62 @@ const AdminCard = (props: AdminCardProps) => {
130173 name : assignmentOrLocation . name ,
131174 isActive : assignmentOrLocation . isActive ,
132175 isHidden : ! isHidden ,
176+ categoryId : isAssignment
177+ ? ( assignmentOrLocation as Assignment ) . categoryId
178+ : undefined ,
179+ categoryIds : isAssignment ? undefined : locationCategoryIds ,
180+ } )
181+ . then ( ( ) => {
182+ context . admin . getAllLocations . invalidate ( ) ;
183+ context . admin . getAllAssignments . invalidate ( ) ;
184+ } )
185+ . catch ( ( err ) => {
186+ toast ( {
187+ title : "Error" ,
188+ description : err . message ,
189+ status : "error" ,
190+ duration : 3000 ,
191+ isClosable : true ,
192+ position : "top-right" ,
193+ } ) ;
194+ } ) ;
195+ } ;
196+
197+ const handleAssignmentCategoryChange = async ( categoryId : number ) => {
198+ setAssignmentCategoryId ( categoryId ) ;
199+ await editMutation
200+ . mutateAsync ( {
201+ id : assignmentOrLocation . id ,
202+ name : assignmentOrLocation . name ,
203+ isActive : isActive ,
204+ isHidden : isHidden ,
205+ categoryId : categoryId ,
206+ } )
207+ . then ( ( ) => {
208+ context . admin . getAllLocations . invalidate ( ) ;
209+ context . admin . getAllAssignments . invalidate ( ) ;
210+ } )
211+ . catch ( ( err ) => {
212+ toast ( {
213+ title : "Error" ,
214+ description : err . message ,
215+ status : "error" ,
216+ duration : 3000 ,
217+ isClosable : true ,
218+ position : "top-right" ,
219+ } ) ;
220+ } ) ;
221+ } ;
222+
223+ const handleLocationCategoriesChange = async ( categoryIds : number [ ] ) => {
224+ setLocationCategoryIds ( categoryIds ) ;
225+ await editMutation
226+ . mutateAsync ( {
227+ id : assignmentOrLocation . id ,
228+ name : assignmentOrLocation . name ,
229+ isActive : isActive ,
230+ isHidden : isHidden ,
231+ categoryIds : categoryIds ,
133232 } )
134233 . then ( ( ) => {
135234 context . admin . getAllLocations . invalidate ( ) ;
@@ -160,59 +259,114 @@ const AdminCard = (props: AdminCardProps) => {
160259 backgroundColor = { boxColor }
161260 justifyContent = "space-between"
162261 >
163- < Flex >
164- < Editable
165- onSubmit = { handleNameChange }
166- textAlign = "center"
167- fontWeight = "semibold"
168- display = "flex"
169- defaultValue = { assignmentOrLocation . name }
170- fontSize = "xl"
171- isPreviewFocusable = { false }
172- >
173- < EditablePreview />
174- < Input as = { EditableInput } />
175- < EditableControls />
176- </ Editable >
177- < Text fontSize = "large" mt = { 1.5 } ml = { 5 } >
178- Active?
179- </ Text >
180- < Switch
181- onChange = { handleActiveChange }
182- mt = { 2.5 }
183- ml = { 3 }
184- isChecked = { isActive }
185- />
186- </ Flex >
187- < Checkbox
188- hidden = { ! isActive || ! isAssignment }
189- onChange = { ( ) => handlePriorityChange ( ! isPriority ) }
190- colorScheme = "telegram"
191- size = "lg"
192- ml = { 2 }
193- isChecked = { isPriority }
194- >
195- Priority
196- </ Checkbox >
197- { ! isActive && (
198- < Flex >
199- { isHidden ? (
200- < FaEyeSlash
201- size = "20px"
202- className = "hover-cursor"
203- style = { { marginTop : "10px" } }
204- onClick = { handleHidden }
205- />
206- ) : (
207- < FaEye
208- size = "20px"
209- className = "hover-cursor"
210- style = { { marginTop : "10px" } }
211- onClick = { handleHidden }
212- />
213- ) }
262+ < >
263+ < Flex w = "50%" >
264+ < Editable
265+ onSubmit = { handleNameChange }
266+ textAlign = "center"
267+ fontWeight = "semibold"
268+ display = "flex"
269+ defaultValue = { assignmentOrLocation . name }
270+ fontSize = "xl"
271+ isPreviewFocusable = { false }
272+ >
273+ < EditablePreview />
274+ < Input as = { EditableInput } />
275+ < EditableControls />
276+ </ Editable >
277+ < Text fontSize = "large" mt = { 1.5 } ml = { 5 } >
278+ Active?
279+ </ Text >
280+ < Switch
281+ onChange = { handleActiveChange }
282+ mt = { 2.5 }
283+ ml = { 3 }
284+ isChecked = { isActive }
285+ />
286+ { /*uppercaseFirstLetter(allCategories?.find((category) => category.id === assignmentCategoryId).name)*/ }
287+ < FormControl w = { isAssignment ? "30%" : "50%" } ml = { 2 } >
288+ { isAssignment ? (
289+ < Select
290+ options = { allCategories ?. map ( ( category ) => ( {
291+ label : category . name ,
292+ value : category . id ,
293+ } ) ) }
294+ value = {
295+ assignmentCategoryId !== undefined
296+ ? {
297+ label : allCategories ?. find (
298+ ( category ) => category . id === assignmentCategoryId ,
299+ ) ?. name ,
300+ value : assignmentCategoryId ,
301+ }
302+ : { label : "" , value : - 1 }
303+ }
304+ onChange = { (
305+ newValue : SingleValue < {
306+ label : string | undefined ;
307+ value : number ;
308+ } > ,
309+ ) => handleAssignmentCategoryChange ( newValue ?. value ?? - 1 ) }
310+ />
311+ ) : (
312+ < Select
313+ isMulti
314+ options = { allCategories ?. map ( ( category ) => ( {
315+ label : category . name ,
316+ value : category . id ,
317+ } ) ) }
318+ value = { allCategories
319+ ?. filter ( ( category ) =>
320+ locationCategoryIds ?. includes ( category . id ) ,
321+ )
322+ ?. map ( ( category ) => ( {
323+ value : category . id ,
324+ label : category . name ,
325+ } ) ) }
326+ onChange = { (
327+ newValue : MultiValue < {
328+ label : string ;
329+ value : number ;
330+ } > ,
331+ ) =>
332+ handleLocationCategoriesChange (
333+ newValue . map ( ( item ) => item . value ) ,
334+ )
335+ }
336+ />
337+ ) }
338+ </ FormControl >
214339 </ Flex >
215- ) }
340+ < Checkbox
341+ hidden = { ! isActive || ! isAssignment }
342+ onChange = { ( ) => handlePriorityChange ( ! isPriority ) }
343+ colorScheme = "telegram"
344+ size = "lg"
345+ ml = { 2 }
346+ isChecked = { isPriority }
347+ >
348+ Priority
349+ </ Checkbox >
350+ { ! isActive && (
351+ < Flex >
352+ { isHidden ? (
353+ < FaEyeSlash
354+ size = "20px"
355+ className = "hover-cursor"
356+ style = { { marginTop : "10px" } }
357+ onClick = { handleHidden }
358+ />
359+ ) : (
360+ < FaEye
361+ size = "20px"
362+ className = "hover-cursor"
363+ style = { { marginTop : "10px" } }
364+ onClick = { handleHidden }
365+ />
366+ ) }
367+ </ Flex >
368+ ) }
369+ </ >
216370 </ Flex >
217371 ) ;
218372} ;
0 commit comments