This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
admin-panel/src/features/QuestionsPage/QuestionsPage.tsx

225 lines
6.4 KiB
TypeScript

import { useState } from 'react';
import { ApolloError, useMutation } from '@apollo/client';
import { useUpdateEffect } from 'react-use';
import {
NumberParam,
StringParam,
useQueryParams,
withDefault,
} from 'use-query-params';
import { useSnackbar } from 'notistack';
import SortParam, { decodeSort } from 'libs/serialize-query-params/SortParam';
import useQuestions from './QuestionsPage.useQuestions';
import { validateRowsPerPage } from 'common/Table/helpers';
import {
MUTATION_CREATE_QUESTION,
MUTATION_UPDATE_QUESTION,
MUTATION_DELETE_QUESTIONS,
} from './mutations';
import { COLUMNS, DEFAULT_SORT, DialogType } from './constants';
import {
Maybe,
MutationCreateQuestionArgs,
MutationDeleteQuestionsArgs,
MutationUpdateQuestionArgs,
Question,
QuestionInput,
} from 'libs/graphql/types';
import {
Button,
Container,
IconButton,
Paper,
Snackbar,
} from '@material-ui/core';
import { Edit as EditIcon } from '@material-ui/icons';
import Table from 'common/Table/Table';
import TableToolbar from './components/TableToolbar/TableToolbar';
import FormDialog from './components/FormDialog/FormDialog';
const QuestionsPage = () => {
const [createQuestionMutation] = useMutation<any, MutationCreateQuestionArgs>(
MUTATION_CREATE_QUESTION,
{ ignoreResults: true }
);
const [updateQuestionMutation] = useMutation<any, MutationUpdateQuestionArgs>(
MUTATION_UPDATE_QUESTION,
{ ignoreResults: true }
);
const [deleteQuestionsMutation] = useMutation<
any,
MutationDeleteQuestionsArgs
>(MUTATION_DELETE_QUESTIONS, { ignoreResults: true });
const [dialogType, setDialogType] = useState<DialogType>(DialogType.None);
const [questionBeingEdited, setQuestionBeingEdited] = useState<
Maybe<Question>
>(null);
const [selectedQuestions, setSelectedQuestions] = useState<Question[]>([]);
const snackbar = useSnackbar();
const [{ page, sort, search, ...rest }, setQueryParams] = useQueryParams({
limit: NumberParam,
page: withDefault(NumberParam, 0),
sort: withDefault(SortParam, DEFAULT_SORT),
search: withDefault(StringParam, ''),
});
const limit = validateRowsPerPage(rest.limit);
const { questions, total, loading, refetch } = useQuestions(
page,
limit,
sort.toString(),
search
);
useUpdateEffect(() => {
if (selectedQuestions.length > 0) {
setSelectedQuestions([]);
}
}, [questions]);
const handleFormDialogSubmit = async (input: QuestionInput) => {
try {
if (dialogType === DialogType.Create) {
await createQuestionMutation({ variables: { input } });
} else {
await updateQuestionMutation({
variables: { input, id: questionBeingEdited?.id ?? -1 },
});
}
await refetch();
snackbar.enqueueSnackbar(
dialogType === DialogType.Create
? 'Pomyślnie utworzono pytanie.'
: 'Zapisano zmiany.',
{ variant: 'success' }
);
return true;
} catch (e) {
snackbar.enqueueSnackbar(
e instanceof ApolloError && e.graphQLErrors.length > 0
? e.graphQLErrors[0].message
: e.message,
{ variant: 'error' }
);
}
return false;
};
const handleDeleteQuestions = async () => {
if (!window.confirm('Czy na pewno chcesz usunąć wybrane zawody?')) {
return;
}
try {
const ids = selectedQuestions.map(question => question.id);
await deleteQuestionsMutation({ variables: { ids } });
await refetch();
snackbar.enqueueSnackbar(`Usuwanie przebiegło pomyślnie.`, {
variant: 'success',
});
} catch (e) {
snackbar.enqueueSnackbar(
e instanceof ApolloError && e.graphQLErrors.length > 0
? e.graphQLErrors[0].message
: e.message,
{ variant: 'error' }
);
}
};
const handleSelect = (checked: boolean, items: Question[]) => {
setSelectedQuestions(prevState =>
checked
? [...prevState, ...items]
: prevState.filter(
item => !items.some(otherItem => otherItem.id === item.id)
)
);
};
return (
<Container>
<Paper>
<TableToolbar
search={search}
onClickCreateQuestion={() => {
setQuestionBeingEdited(null);
setDialogType(DialogType.Create);
}}
onChangeSearchValue={val => {
setQueryParams({ page: 0, search: val });
}}
/>
<Table
selection
columns={COLUMNS}
data={questions}
selected={selectedQuestions}
onSelect={handleSelect}
actions={[
{
icon: row => {
return (
<IconButton
onClick={() => {
setQuestionBeingEdited(row);
setDialogType(DialogType.Edit);
}}
>
<EditIcon />
</IconButton>
);
},
tooltip: 'Edytuj',
},
]}
loading={loading}
orderBy={sort.orderBy}
orderDirection={sort.orderDirection}
onRequestSort={(orderBy, orderDirection) => {
setQueryParams({
page: 0,
sort: decodeSort(orderBy + ' ' + orderDirection),
});
}}
footerProps={{
count: total,
page,
onChangePage: page => {
setQueryParams({ page });
},
onChangeRowsPerPage: limit => {
setQueryParams({ page: 0, limit });
},
rowsPerPage: limit,
}}
/>
</Paper>
<FormDialog
open={
dialogType === DialogType.Create || dialogType === DialogType.Edit
}
question={questionBeingEdited}
onSubmit={handleFormDialogSubmit}
onClose={() => setDialogType(DialogType.None)}
/>
<Snackbar
open={selectedQuestions.length > 0}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
message={`Wybrane pytania: ${selectedQuestions.length}`}
action={
<>
<Button onClick={handleDeleteQuestions} color="secondary">
Usuń
</Button>
<Button color="secondary" onClick={() => setSelectedQuestions([])}>
Anuluj
</Button>
</>
}
/>
</Container>
);
};
export default QuestionsPage;