Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add questionings filters #98

Merged
merged 4 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/hooks/useSearchFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@ import { FormEventHandler, useState } from "react";
import { create } from "zustand";
import { combine } from "zustand/middleware";

export type QuestioningsBaseType = {
searchParam: string;
state: string;
page: number;
pageSize: number;
lastEvent?: string[];
lastCommunication?: string[];
campaignId?: string;
};

export const base = {
contacts: {
searchParam: "",
Expand All @@ -13,9 +23,13 @@ export const base = {
},
questionings: {
searchParam: "",
state: "all",
page: 0,
pageSize: 10,
},
lastEvent: [],
lastCommunication: [],
campaignId: "",
} as QuestioningsBaseType,
surveys: {
idSource: "",
year: undefined as undefined | number,
Expand Down Expand Up @@ -88,6 +102,7 @@ export function useSearchForm<K extends Key>(key: K, initialValue: State[K]) {
value,
onSubmit,
onReset,
setValue,
inputProps: (name: keyof State[K]) => ({
id: name,
name: name,
Expand Down
15 changes: 11 additions & 4 deletions src/pages/ContactPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { theme } from "../theme.tsx";
import { Button, Typography } from "@mui/material";
import { ContactDetailsCard } from "../ui/Contact/ContactDetailsCard.tsx";
import { ContactCampaignsCard } from "../ui/Contact/ContactCampaignsCard.tsx";
import { Link } from "../ui/Link.tsx";
import { useSetSearchFilter } from "../hooks/useSearchFilter.ts";
import { useGetSearchFilter, useSetSearchFilter } from "../hooks/useSearchFilter.ts";
import { LinkWithForwardRef } from "../ui/Link.tsx";

export const ContactPage = () => {
const setFilter = useSetSearchFilter();
Expand All @@ -22,6 +22,8 @@ export const ContactPage = () => {
},
});

const { questionings: questioningFilter } = useGetSearchFilter();

if (!contact) {
return (
<Row justifyContent="center" py={10}>
Expand Down Expand Up @@ -53,10 +55,15 @@ export const ContactPage = () => {
<Button
variant="contained"
size="large"
component={Link}
component={LinkWithForwardRef}
to={`/questionings`}
onClick={() => {
return setFilter("questionings", { searchParam: contactName, page: 0, pageSize: 10 });
return setFilter("questionings", {
...questioningFilter,
page: 0,
pageSize: 10,
searchParam: contact.identifier,
});
}}
disabled={contact.listCampaigns?.length === 0}
>
Expand Down
55 changes: 22 additions & 33 deletions src/pages/Logout.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,33 @@
import { Stack, Typography, Box, Link } from "@mui/material";
import { Stack, Typography, Box, Card, Button } from "@mui/material";
import { Link } from "../ui/Link.tsx";
import { Row } from "../ui/Row.tsx";
import { PropsWithChildren } from "react";
import { Link as RouterLink } from "react-router-dom";

export function LogoutPage() {
return (
<>
<Stack
position="relative"
sx={{
background: "linear-gradient(270deg, #21005D 0%, #9A82DB 0%, #E12358 90%)",
}}
justifyContent="center"
alignItems="center"
minHeight={500}
height="calc(100vh - 230px)"
>
<Typography variant="displaySmall" fontWeight={400} color="white">
{"Vous avez été deconnecté,"}
</Typography>
<Row spacing={2}>
<Typography variant="displaySmall" fontWeight={400} color="white">
{"pour revenir sur "}
</Typography>
<Row typography="headlineMedium" gap={0.25} color="red.main" component="span">
<Box
sx={{
width: "90vw",
height: "90vh",
display: "flex",
justifyContent: "center",
alignItems: "center",
margin: "auto",
}}
>
<Card sx={{ p: 5, width: "500px" }} elevation={2}>
<Stack gap={5} alignItems={"center"}>
<Row typography="headlineLarge" gap={0.5} color="red.main" component="span">
<Box component="span" color="black.main" fontWeight={600}>
Platine
</Box>
Gestion
</Row>
,
</Row>
<Typography variant="displaySmall" fontWeight={400} color="white" component={HomeLink}>
{"cliquez ici"}
</Typography>
</Stack>
</>
<Typography variant="headlineLarge">Vous avez été déconnecté.</Typography>
<Button variant="contained" sx={{ py: 1 }} component={Link} to={"/"}>
Se reconnecter
</Button>
</Stack>
</Card>
</Box>
);
}

const HomeLink = (props: PropsWithChildren) => {
return <Link component={RouterLink} underline="none" to="/" {...props} />;
};
5 changes: 3 additions & 2 deletions src/pages/QuestioningPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { SyntheticEvent, useState } from "react";
import { theme } from "../theme.tsx";
import { Breadcrumbs } from "../ui/Breadcrumbs.tsx";
import { Row } from "../ui/Row.tsx";
import { Link } from "../ui/Link.tsx";
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
import { PageTab } from "../ui/PageTab.tsx";
import { QuestioningInfos } from "../ui/Questioning/QuestioningInfos.tsx";
import { collectStatus } from "../constants/collectStatus.ts";
import { getCollectStateChipColor } from "../ui/Questioning/SearchQuestioningTable.tsx";
import { useParams } from "react-router-dom";
import { useFetchQuery } from "../hooks/useFetchQuery.ts";
import { LinkWithForwardRef } from "../ui/Link.tsx";

enum Tab {
Infos = "Infos",
Expand Down Expand Up @@ -83,8 +83,9 @@ export const QuestioningPage = () => {
variant="contained"
disabled={hasNoQuestioningUrl}
size="large"
component={Link}
component={LinkWithForwardRef}
to={questioning.readOnlyUrl ?? ""}
target="_blank"
endIcon={<OpenInNewIcon />}
>
Voir le questionnaire miroir
Expand Down
97 changes: 72 additions & 25 deletions src/pages/Search/SearchQuestionings.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FormEventHandler, useState } from "react";
import { useState } from "react";
import {
QuestioningsBaseType,
useGetSearchFilter,
useSearchFilterParams,
useSearchForm,
Expand All @@ -12,41 +13,58 @@ import { Breadcrumbs } from "../../ui/Breadcrumbs.tsx";
import { Divider, ToggleButton, ToggleButtonGroup, Typography } from "@mui/material";
import { SearchQuestioningTable } from "../../ui/Questioning/SearchQuestioningTable.tsx";
import { EmptyState } from "../../ui/TableComponents.tsx";
import { SearchTextField } from "../../ui/SearchTextField.tsx";
import { useFetchQuery } from "../../hooks/useFetchQuery.ts";
import { MultipleSearchSelect } from "../../ui/Search/MultipleSearchSelect.tsx";
import { collectStatus } from "../../constants/collectStatus.ts";
import { FilterSelect } from "../../ui/FilterSelect.tsx";
import { communicationsList } from "../../constants/communications.ts";
import { SearchQuestioningTextField } from "../../ui/Search/SearchQuestioningTextField.tsx";

const endpoint = "/api/questionings/search";

export const SearchQuestionings = () => {
const breadcrumbs = [{ href: "/", title: "Accueil" }, "Interrogations"];

const [tab, setTab] = useState("me");
const [stateFilter, setStateFilter] = useState("all");

const { questionings: questioningFilter } = useGetSearchFilter();
const setFilter = useSetSearchFilter();

// filter to remove empty parameters from the query
const searchFilterParams = Object.fromEntries(
Object.entries(useSearchFilterParams("questionings"))
.map(([key, value]) => {
if (Array.isArray(value)) {
value = value.filter(v => v !== undefined);
}
return [key, value];
})
.filter(([, value]) => value !== undefined && !(Array.isArray(value) && value.length === 0)),
);

const { data, isLoading } = useFetchQuery(endpoint, {
query: {
...useSearchFilterParams("questionings"),
...searchFilterParams,
},
});

const questionings = data?.content ?? [];

const { onSubmit, onReset, inputProps, value } = useSearchForm("questionings", questioningFilter);

const handleSubmit: FormEventHandler = e => {
onSubmit(e);
};

const handleReset: FormEventHandler = e => {
onReset(e);
};
const { onReset, inputProps, value, setValue } = useSearchForm("questionings", questioningFilter);

const hasResetButton = value.searchParam !== "";

const hasNoQuestioning = !isLoading && questionings.length === 0;

const onResetSelect = (name: keyof QuestioningsBaseType) => {
setValue({ ...value, [name]: [] });
setFilter("questionings", { ...questioningFilter, [name]: [] });
};

const onSubmit = (name: keyof QuestioningsBaseType) => {
setFilter("questionings", { ...questioningFilter, [name]: inputProps(name).value });
};

return (
<Stack>
<Row
Expand All @@ -73,13 +91,13 @@ export const SearchQuestionings = () => {
</Row>
</Row>
<Divider variant="fullWidth" />
<form onSubmit={handleSubmit} onReset={handleReset}>
<form>
<Stack sx={{ my: 3, px: 5 }} gap={3}>
<Row justifyContent={"space-between"}>
<ToggleButtonGroup
value={stateFilter}
value={questioningFilter.state}
exclusive
onChange={(_, v) => setStateFilter(v)}
onChange={(_, value) => setFilter("questionings", { ...questioningFilter, state: value })}
sx={{
boxShadow: "none",
".MuiToggleButtonGroup-grouped:not(:first-of-type)": {
Expand All @@ -105,17 +123,46 @@ export const SearchQuestionings = () => {
</ToggleButton>
</ToggleButtonGroup>
</Row>
<SearchTextField
<SearchQuestioningTextField
hasResetButton={hasResetButton}
onReset={() => {
setFilter("questionings", { ...questioningFilter, "searchParam": "" });
setValue({ ...value, "searchParam": "" });
}}
onSubmit={() => onSubmit("searchParam")}
label={"Rechercher par unité enquêtée ou identifiant de connexion"}
inputProps={inputProps as any}
inputProps={{
...inputProps("searchParam"),
value: inputProps("searchParam").value as QuestioningsBaseType["searchParam"],
}}
/>
{/* TODO: use it later
<Row gap={3}>
<FilterSelect options={[]} label={"Collecte"} name={"campaignId"} />
<SearchSelectStatus />
<FilterSelect options={[]} label={"Dernière communication"} name={"lastCommunication"} />
</Row> */}
<Row gap={3}>
<FilterSelect
label={"Collecte"}
questioningFilter={questioningFilter}
setFilter={setFilter}
/>
<MultipleSearchSelect
options={collectStatus}
inputProps={{
...inputProps("lastEvent"),
value: inputProps("lastEvent").value as string[],
}}
label={"Statut"}
onReset={() => onResetSelect("lastEvent")}
onSubmit={() => onSubmit("lastEvent")}
/>
<MultipleSearchSelect
options={communicationsList}
inputProps={{
...inputProps("lastCommunication"),
value: inputProps("lastCommunication").value as string[],
}}
label={"Dernière communication"}
onReset={() => onResetSelect("lastCommunication")}
onSubmit={() => onSubmit("lastCommunication")}
/>
</Row>
{hasNoQuestioning && (
<EmptyState
isFiltered={hasResetButton}
Expand All @@ -126,7 +173,7 @@ export const SearchQuestionings = () => {
{!hasNoQuestioning && (
<SearchQuestioningTable
questionings={questionings}
stateFilter={stateFilter}
stateFilter={questioningFilter.state}
isLoading={isLoading}
totalCount={data?.totalElements ?? 0}
questioningFilter={questioningFilter}
Expand Down
28 changes: 28 additions & 0 deletions src/theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,34 @@ export const theme = createTheme({
},
],
},
MuiAutocomplete: {
styleOverrides: {
clearIndicator: {
color: palette.primary.main,
visibility: "visible",
},
popupIndicator: {
color: palette.primary.main,
},
groupLabel: {
...typography.titleSmall,
color: palette.black.main,
},
option: {
"&[aria-selected='true']": {
backgroundColor: "white !important",
},
},
inputRoot: {
".MuiOutlinedInput-notchedOutline": {
borderColor: palette.border.default,
},
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
border: `1px solid ${palette.primary.main}`,
},
},
},
},
MuiIconButton: {
variants: [
{
Expand Down
Loading
Loading