-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #204 from dump-hr/admin-interest-page
Admin interest page
- Loading branch information
Showing
11 changed files
with
252 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { InterestDto, InterestModifyDto } from '@ddays-app/types'; | ||
import toast from 'react-hot-toast'; | ||
import { useMutation, useQueryClient } from 'react-query'; | ||
|
||
import { api } from '..'; | ||
|
||
const interestCreate = async (dto: InterestModifyDto) => { | ||
return await api.post<InterestModifyDto, InterestDto>('/interest', dto); | ||
}; | ||
|
||
export const useInterestCreate = () => { | ||
const queryClient = useQueryClient(); | ||
|
||
return useMutation(interestCreate, { | ||
onSuccess: () => { | ||
queryClient.invalidateQueries(['interest']); | ||
toast.success('Interes uspješno dodan!'); | ||
}, | ||
onError: (error: string) => { | ||
toast.error(error); | ||
}, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { InterestDto } from '@ddays-app/types'; | ||
import { QueryOptions, useQuery } from 'react-query'; | ||
|
||
import { api } from '..'; | ||
|
||
const interestGetOne = async (id: number) => { | ||
return await api.get<never, InterestDto>(`/interest/${id}`); | ||
}; | ||
|
||
export const useInterestGetOne = ( | ||
id?: number, | ||
options?: QueryOptions<InterestDto>, | ||
) => { | ||
return useQuery(['interest', id], () => interestGetOne(id!), { | ||
enabled: !!id, | ||
...options, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { InterestDto } from '@ddays-app/types'; | ||
import toast from 'react-hot-toast'; | ||
import { useMutation, useQueryClient } from 'react-query'; | ||
|
||
import { api } from '..'; | ||
|
||
const interestRemove = async (id: number) => { | ||
return await api.delete<never, InterestDto>(`/interest/${id}`); | ||
}; | ||
|
||
export const useInterestRemove = () => { | ||
const queryClient = useQueryClient(); | ||
|
||
return useMutation(interestRemove, { | ||
onSuccess: () => { | ||
queryClient.invalidateQueries(['interest']); | ||
toast.success('Interest uspješno uklonjen!'); | ||
}, | ||
onError: (error: string) => { | ||
toast.error(error); | ||
}, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { InterestDto, InterestModifyDto } from '@ddays-app/types'; | ||
import toast from 'react-hot-toast'; | ||
import { useMutation, useQueryClient } from 'react-query'; | ||
|
||
import { api } from '..'; | ||
|
||
const interestUpdate = async (dto: InterestModifyDto & { id: number }) => { | ||
return await api.patch<InterestModifyDto, InterestDto>( | ||
`/interest/${dto.id}`, | ||
{ | ||
...dto, | ||
id: undefined, | ||
}, | ||
); | ||
}; | ||
|
||
export const useInterestUpdate = () => { | ||
const queryClient = useQueryClient(); | ||
|
||
return useMutation(interestUpdate, { | ||
onSuccess: (updatedInterest) => { | ||
queryClient.invalidateQueries(['interest']); | ||
queryClient.invalidateQueries(['interest', updatedInterest.id]); | ||
toast.success('Uređivanje interesa uspješno uređeno!'); | ||
}, | ||
onError: (error: string) => { | ||
toast.error(error); | ||
}, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { InterestModifyDto, Theme } from '@ddays-app/types'; | ||
import { classValidatorResolver } from '@hookform/resolvers/class-validator'; | ||
import { useForm } from 'react-hook-form'; | ||
|
||
import { useInterestCreate } from '../api/interest/useInterestCreate'; | ||
import { useInterestGetOne } from '../api/interest/useInterestGetOne'; | ||
import { useInterestUpdate } from '../api/interest/useInterestUpdate'; | ||
import { Button } from '../components/Button'; | ||
import { InputHandler } from '../components/InputHandler'; | ||
import { Question, QuestionType } from '../types/question'; | ||
|
||
type InterestFormProps = { | ||
id?: number; | ||
onSuccess: () => void; | ||
}; | ||
|
||
export const InterestForm: React.FC<InterestFormProps> = ({ | ||
id, | ||
onSuccess, | ||
}) => { | ||
const { data: interest, isLoading } = useInterestGetOne(id); | ||
|
||
const updateInterest = useInterestUpdate(); | ||
const createInterest = useInterestCreate(); | ||
|
||
const questions: Question[] = [ | ||
{ | ||
id: 'name', | ||
type: QuestionType.Field, | ||
title: 'Ime', | ||
defaultValue: interest?.name, | ||
}, | ||
{ | ||
id: 'theme', | ||
type: QuestionType.Select, | ||
title: 'Područje interesa', | ||
options: Object.values(Theme), | ||
defaultValue: interest?.theme, | ||
}, | ||
]; | ||
|
||
const form = useForm<InterestModifyDto>({ | ||
resolver: classValidatorResolver(InterestModifyDto), | ||
}); | ||
|
||
if (id && isLoading) { | ||
return <div>Loading...</div>; | ||
} | ||
|
||
return ( | ||
<> | ||
{questions.map((q) => ( | ||
<InputHandler question={q} form={form} key={q.id} /> | ||
))} | ||
|
||
<Button | ||
onClick={form.handleSubmit(async (formData) => { | ||
if (id) { | ||
await updateInterest.mutateAsync({ ...formData, id }); | ||
} else { | ||
await createInterest.mutateAsync(formData); | ||
} | ||
onSuccess(); | ||
})}> | ||
Submit | ||
</Button> | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { useState } from 'react'; | ||
|
||
import { useInterestGetAll } from '../api/interest/useInterestGetAll'; | ||
import { useInterestRemove } from '../api/interest/useInterestRemove'; | ||
import { Button } from '../components/Button'; | ||
import { Modal } from '../components/Modal'; | ||
import { Table } from '../components/Table'; | ||
import { InterestForm } from '../forms/InterestForm'; | ||
|
||
export const InterestPage = () => { | ||
const [isModalOpen, setIsModalOpen] = useState(false); | ||
const [interestToEditId, setInterestToEditId] = useState<number>(); | ||
|
||
const interests = useInterestGetAll(); | ||
|
||
const removeInterest = useInterestRemove(); | ||
|
||
if (interests.isLoading) { | ||
return <div>Loading...</div>; | ||
} | ||
|
||
return ( | ||
<> | ||
<Modal | ||
isOpen={isModalOpen} | ||
onClose={() => { | ||
setIsModalOpen(false); | ||
setInterestToEditId(undefined); | ||
}}> | ||
<InterestForm | ||
id={interestToEditId} | ||
onSuccess={() => { | ||
setIsModalOpen(false); | ||
setInterestToEditId(undefined); | ||
}} | ||
/> | ||
</Modal> | ||
|
||
<Button variant='primary' onClick={() => setIsModalOpen(true)}> | ||
New | ||
</Button> | ||
|
||
<Table | ||
data={interests.data} | ||
actions={[ | ||
{ | ||
label: 'Uredi', | ||
action: (interest) => { | ||
setInterestToEditId(interest.id); | ||
setIsModalOpen(true); | ||
}, | ||
}, | ||
{ | ||
label: 'Obriši', | ||
action: (interest) => { | ||
if (confirm('Jesi li siguran?')) { | ||
removeInterest.mutateAsync(interest.id); | ||
} | ||
}, | ||
}, | ||
]} | ||
/> | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters