Skip to content

Commit

Permalink
add FollowOrganizationUnitCard and FollowSurveyCard
Browse files Browse the repository at this point in the history
  • Loading branch information
RenauxLeaInsee committed Apr 24, 2024
1 parent 5b8c1b0 commit f0e2d2d
Show file tree
Hide file tree
Showing 11 changed files with 269 additions and 20 deletions.
3 changes: 3 additions & 0 deletions src/i18n-en.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ export const messagesEn = {
chooseInterviewer: "Choose an interviewer :",
chooseOrganizationUnit: "Choose an organization unit :",
followInterviewer: "Follow an interviewer",
followSurvey: 'Follow a survey',
allSurveys: 'All surveys',
followOrganizationUnit: "Follow an organization unit"
}
4 changes: 3 additions & 1 deletion src/i18n-fr.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,7 @@ export const messagesFr = {
chooseInterviewer: "Choisissez un enquêteur / une enquêtrice :",
chooseOrganizationUnit: "Choisissez un site :",
followInterviewer: "Suivre un enquêteur",

followSurvey: "Suivre une enquête",
allSurveys: "Ensemble des enquêtes",
followOrganizationUnit: "Suivre un site"
}
5 changes: 5 additions & 0 deletions src/pages/FollowCampaignPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Typography } from "@mui/material";

export const FollowCampaignPage = () => {
return <Typography>page suivre enquête</Typography>;
};
5 changes: 5 additions & 0 deletions src/pages/FollowInterviewerPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Typography } from "@mui/material";

export const FollowInterviewerPage = () => {
return <Typography>page suivre enquêteur</Typography>;
};
5 changes: 5 additions & 0 deletions src/pages/FollowOrganizationUnitPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Typography } from "@mui/material";

export const FollowOrganizationUnitPage = () => {
return <Typography>page suivre site</Typography>;
};
6 changes: 6 additions & 0 deletions src/pages/FollowPage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { Row } from "../ui/Row";
import { FollowInterviewerCard } from "../ui/FollowInterviewerCard";
import { FollowSurveyCard } from "../ui/FollowSurveyCard";
import { FollowOrganizationUnitCard } from "../ui/FollowOrganizationUnitCard";

export const FollowPage = () => {
// TODO use real condition
const isNationalProfile = true;

// TODO call api to get interviewers, surveys and organizationUnits

const gridTemplateColumns = isNationalProfile
? { gridTemplateColumns: "1fr 1fr 1fr" }
: { gridTemplateColumns: "1fr 1fr" };
Expand All @@ -21,7 +25,9 @@ export const FollowPage = () => {
px={4}
py={3}
>
<FollowSurveyCard />
<FollowInterviewerCard />
{isNationalProfile && <FollowOrganizationUnitCard />}
</Row>
);
};
6 changes: 6 additions & 0 deletions src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { ClosePage } from "./pages/ClosePage";
import { NotifyPage } from "./pages/NotifyPage";
import { CollectOrganizationPage } from "./pages/CollectOrganizationPage";
import { ReassignmentPage } from "./pages/ReassignmentPage";
import { FollowInterviewerPage } from "./pages/FollowInterviewerPage";
import { FollowCampaignPage } from "./pages/FollowCampaignPage";
import { FollowOrganizationUnitPage } from "./pages/FollowOrganizationUnitPage";

export const routes: RouteObject[] = [
{
Expand All @@ -21,6 +24,9 @@ export const routes: RouteObject[] = [
children: [
{ path: "", element: <Home /> },
{ path: "follow", element: <FollowPage /> },
{ path: "follow/interviewer/:id", element: <FollowInterviewerPage /> },
{ path: "follow/campaign/:id", element: <FollowCampaignPage /> },
{ path: "follow/organization-unit/:id", element: <FollowOrganizationUnitPage /> },
{ path: "read", element: <ReadPage /> },
{ path: "close", element: <ClosePage /> },
{ path: "notify", element: <NotifyPage /> },
Expand Down
30 changes: 30 additions & 0 deletions src/ui/FollowCardHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import { useIntl } from "react-intl";
import { SearchField } from "./SearchField";
import { ChangeEvent } from "react";

type Props = {
title: string;
placeholder: string;
onSearch: (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
};

export const FollowCardHeader = ({ title, placeholder, onSearch }: Props) => {
const intl = useIntl();

const handleChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
onSearch(e);
};

return (
<Stack gap={3}>
<Typography variant="headlineLarge">{intl.formatMessage({ id: title })}</Typography>
<SearchField
onChange={handleChange}
label={intl.formatMessage({ id: "toSearchLabel" })}
placeholder={intl.formatMessage({ id: placeholder })}
/>
</Stack>
);
};
73 changes: 54 additions & 19 deletions src/ui/FollowInterviewerCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import { useIntl } from "react-intl";
import { useDebouncedState } from "../hooks/useDebouncedState";
import Card from "@mui/material/Card";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import { SearchField } from "./SearchField";
import TableContainer from "@mui/material/TableContainer";
import Table from "@mui/material/Table";
import TableHead from "@mui/material/TableHead";
import { TableBody, TableCell, TableRow } from "@mui/material";
import { useState } from "react";
import { APISchemas } from "../types/api";
import { Link as RouterLink } from "react-router-dom";
import { Link } from "./Link";
import { FollowCardHeader } from "./FollowCardHeader";

const interviewersMock = [
{
Expand Down Expand Up @@ -40,24 +43,22 @@ const interviewersMock = [
export const FollowInterviewerCard = () => {
const intl = useIntl();
const [search, setSearch] = useDebouncedState("", 500);
// const [page, setPage] = useState(0);
const [page, setPage] = useState(0);

Check failure on line 46 in src/ui/FollowInterviewerCard.tsx

View workflow job for this annotation

GitHub Actions / test_lint

'page' is assigned a value but never used

Check failure on line 46 in src/ui/FollowInterviewerCard.tsx

View workflow job for this annotation

GitHub Actions / test_lint

'page' is assigned a value but never used

// const handleChangePage = (_: React.MouseEvent<HTMLButtonElement> | null, newPage: number) => {
// setPage(newPage);
// };
const handleChangePage = (_: React.MouseEvent<HTMLButtonElement> | null, newPage: number) => {

Check failure on line 48 in src/ui/FollowInterviewerCard.tsx

View workflow job for this annotation

GitHub Actions / test_lint

'handleChangePage' is assigned a value but never used

Check failure on line 48 in src/ui/FollowInterviewerCard.tsx

View workflow job for this annotation

GitHub Actions / test_lint

'handleChangePage' is assigned a value but never used
setPage(newPage);
};

const filteredInterviewers = filterInterviewers({ interviewers: interviewersMock, search });

return (
<Card variant="general" sx={{ height: "calc(100vh - 140px)", py: 4, px: 3 }}>
<Card variant="general" sx={{ height: "calc(100vh - 140px)", py: 4, px: 3, overflow: "auto" }}>
<Stack gap={3}>
<Typography variant="headlineLarge">
{intl.formatMessage({ id: "followInterviewer" })}
</Typography>
<SearchField
onChange={e => setSearch(e.target.value)}
label={intl.formatMessage({ id: "toSearchLabel" })}
placeholder={intl.formatMessage({ id: "searchInterviewer" })}
<FollowCardHeader
title={"followInterviewer"}
onSearch={e => setSearch(e.target.value)}
placeholder="searchInterviewer"
/>

<TableContainer>
<Table aria-label="interviewer list" size="small" sx={{ typography: "bodyMedium" }}>
<TableHead>
Expand All @@ -68,11 +69,18 @@ export const FollowInterviewerCard = () => {
</TableRow>
</TableHead>
<TableBody>
{interviewersMock.map(interviewer => (
{filteredInterviewers.map(interviewer => (
<TableRow key={interviewer.id}>
<TableCell>
{interviewer.interviewerLastName.toLocaleUpperCase()}{" "}
{interviewer.interviewerFirstName}
<TableCell sx={{ py: 0.5 }}>
<Link
color="inherit"
component={RouterLink}
underline="none"
to={`/follow/interviewer/${interviewer.id}`}
>
{interviewer.interviewerLastName?.toLocaleUpperCase()}{" "}
{interviewer.interviewerFirstName}
</Link>
</TableCell>
</TableRow>
))}
Expand All @@ -84,3 +92,30 @@ export const FollowInterviewerCard = () => {
</Card>
);
};

type FilterInterviewerProps = {
interviewers: APISchemas["InterviewerDto"][];
search?: string;
};

const filterInterviewers = ({ interviewers, search }: FilterInterviewerProps) => {
if (search) {
interviewers = interviewers.filter(
item =>
item.interviewerFirstName?.toLowerCase().includes(search.toLowerCase()) ||
item.interviewerLastName?.toLowerCase().includes(search.toLowerCase()) ||
(item.interviewerFirstName &&
item.interviewerLastName &&
(item.interviewerFirstName
?.toLowerCase()
.concat(item.interviewerLastName?.toLowerCase())
.includes(search.split(" ").join("").toLowerCase()) ||
item.interviewerLastName
?.toLowerCase()
.concat(item.interviewerFirstName?.toLowerCase())
.includes(search.split(" ").join("").toLowerCase()))),
);
}

return interviewers;
};
100 changes: 100 additions & 0 deletions src/ui/FollowOrganizationUnitCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { useIntl } from "react-intl";
import { useDebouncedState } from "../hooks/useDebouncedState";
import Card from "@mui/material/Card";
import Stack from "@mui/material/Stack";
import TableContainer from "@mui/material/TableContainer";
import Table from "@mui/material/Table";
import TableHead from "@mui/material/TableHead";
import { TableBody, TableCell, TableRow } from "@mui/material";
import { useState } from "react";
import { Link as RouterLink } from "react-router-dom";
import { Link } from "./Link";
import { FollowCardHeader } from "./FollowCardHeader";

const OUMock = [
{
id: "1",
label: "Paris",
},
{
id: "2",
label: "Metz",
},
{
id: "3",

label: "Lille",
},
{
id: "4",

label: "Amiens",
},
];

export const FollowOrganizationUnitCard = () => {
const intl = useIntl();
const [search, setSearch] = useDebouncedState("", 500);
const [page, setPage] = useState(0);

Check failure on line 38 in src/ui/FollowOrganizationUnitCard.tsx

View workflow job for this annotation

GitHub Actions / test_lint

'page' is assigned a value but never used

Check failure on line 38 in src/ui/FollowOrganizationUnitCard.tsx

View workflow job for this annotation

GitHub Actions / test_lint

'page' is assigned a value but never used

const handleChangePage = (_: React.MouseEvent<HTMLButtonElement> | null, newPage: number) => {

Check failure on line 40 in src/ui/FollowOrganizationUnitCard.tsx

View workflow job for this annotation

GitHub Actions / test_lint

'handleChangePage' is assigned a value but never used

Check failure on line 40 in src/ui/FollowOrganizationUnitCard.tsx

View workflow job for this annotation

GitHub Actions / test_lint

'handleChangePage' is assigned a value but never used
setPage(newPage);
};

const filteredOU = filterOrganizationUnits({ organizationUnits: OUMock, search });

return (
<Card variant="general" sx={{ height: "calc(100vh - 140px)", py: 4, px: 3, overflow: "auto" }}>
<Stack gap={3}>
<FollowCardHeader
title={"followOrganizationUnit"}
onSearch={e => setSearch(e.target.value)}
placeholder="searchOrganizationUnit"
/>
<TableContainer>
<Table aria-label="organization unit list" size="small" sx={{ typography: "bodyMedium" }}>
<TableHead>
<TableRow>
<TableCell sx={{ color: "text.tertiary" }}>
{intl.formatMessage({ id: "chooseOrganizationUnit" })}
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{filteredOU.map(OU => (
<TableRow key={OU.id}>
<TableCell sx={{ py: 0.5 }}>
<Link
color="inherit"
component={RouterLink}
underline="none"
to={`/follow/organization-unit/${OU.id}`}
>
{OU.label}
</Link>
</TableCell>
</TableRow>
))}
</TableBody>
{/* TODO use TableFooter */}
</Table>
</TableContainer>
</Stack>
</Card>
);
};

type FilterOUProps = {
organizationUnits: { id: string; label: string }[];
search?: string;
};

const filterOrganizationUnits = ({ organizationUnits, search }: FilterOUProps) => {
if (search) {
organizationUnits = organizationUnits.filter(item =>
item.label.toLowerCase().includes(search.toLowerCase()),
);
}

return organizationUnits;
};
52 changes: 52 additions & 0 deletions src/ui/FollowSurveyCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useIntl } from "react-intl";
import Card from "@mui/material/Card";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import { Link } from "./Link";
import { Link as RouterLink } from "react-router-dom";

const surveysMock = [
{
id: "1",
label: "Logement",
},
{
id: "2",
label: "Autonomie",
},
{
id: "3",
label: "TIC",
},
];

export const FollowSurveyCard = () => {
const intl = useIntl();

return (
<Card variant="general" sx={{ height: "calc(100vh - 140px)", py: 4, px: 3, overflow: "auto" }}>
<Stack gap={3}>
<Typography variant="headlineLarge">{intl.formatMessage({ id: "followSurvey" })}</Typography>

<Stack gap={1.5} typography={"bodyMedium"}>
<Box color={"text.tertiary"}>{intl.formatMessage({ id: "chooseSurvey" })}</Box>
<Stack gap={0.5}>
{surveysMock.map(survey => (
<Link
key={survey.id}
color="inherit"
component={RouterLink}
underline="none"
to={`/follow/campaign/${survey.id}`}
>
{survey.label}
</Link>
))}
</Stack>
<Box>{intl.formatMessage({ id: "allSurveys" })}</Box>
</Stack>
</Stack>
</Card>
);
};

0 comments on commit f0e2d2d

Please sign in to comment.