Skip to content

Commit

Permalink
Ajout d'un annuaire des conseillers sur le site
Browse files Browse the repository at this point in the history
  • Loading branch information
mariheck committed May 28, 2024
1 parent e1dbcfc commit 9e2a7b0
Show file tree
Hide file tree
Showing 15 changed files with 423 additions and 7 deletions.
2 changes: 1 addition & 1 deletion packages/site/app/actus/[id]/[slug]/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const getData = async (id: number) => {
]);

if (data) {
const idList = await fetchCollection('actualites', [
const {data: idList} = await fetchCollection('actualites', [
['fields[0]', 'DateCreation'],
['fields[1]', 'createdAt'],
['fields[2]', 'Epingle'],
Expand Down
2 changes: 1 addition & 1 deletion packages/site/app/actus/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type ActuCard = {
};

const getData = async () => {
const data = await fetchCollection('actualites', [
const {data} = await fetchCollection('actualites', [
['populate[0]', 'Couverture'],
['sort[0]', 'createdAt:desc'],
]);
Expand Down
2 changes: 1 addition & 1 deletion packages/site/app/collectivites/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const fetchCollectivite = async (code_siren_insee: string) => {
};

export const getStrapiData = async (codeSirenInsee: string) => {
const data = await fetchCollection('collectivites', [
const {data} = await fetchCollection('collectivites', [
['filters[code_siren_insee]', `${codeSirenInsee}`],
['populate[0]', 'seo'],
['populate[1]', 'seo.metaImage'],
Expand Down
2 changes: 1 addition & 1 deletion packages/site/app/faq/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export type FaqData = {
};

const getData = async () => {
const data = await fetchCollection('faqs');
const {data} = await fetchCollection('faqs');

const formattedData = data
? sortByRank(data).map(d => ({
Expand Down
5 changes: 5 additions & 0 deletions packages/site/app/programme/Ressources.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ const Ressources = ({description}: RessourcesProps) => {
href: '/ressources',
variant: 'outlined',
},
{
title: 'Annuaire des conseillers',
href: '/programme/annuaire',
variant: 'outlined',
},
{
title: 'Lire les questions fréquentes',
href: '/faq',
Expand Down
2 changes: 1 addition & 1 deletion packages/site/app/programme/[uid]/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import {StrapiItem} from 'src/strapi/StrapiItem';

export const getServiceStrapiData = async (uid: string) => {
const data = await fetchCollection('services', [
const {data} = await fetchCollection('services', [
['filters[uid]', `${uid}`],
['populate[0]', 'seo'],
['populate[1]', 'seo.metaImage'],
Expand Down
128 changes: 128 additions & 0 deletions packages/site/app/programme/annuaire/CarteConseiller.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
'use client';

import {useState} from 'react';
import {Icon, Tooltip, useCopyToClipboard} from '@tet/ui';
import {StrapiItem} from 'src/strapi/StrapiItem';
import {StrapiImage} from '@components/strapiImage/StrapiImage';

type CarteConseillerProps = {
prenom: string;
nom: string;
structure: string;
region: string;
ville: string;
email: string;
linkedin?: string;
site?: string;
photo?: StrapiItem;
};

const CarteConseiller = ({
prenom,
nom,
structure,
region,
ville,
email,
linkedin,
site,
photo,
}: CarteConseillerProps) => {
const [displayCopyMsg, setDisplayCopyMsg] = useState(false);
const {copy} = useCopyToClipboard();

return (
<div className="bg-white px-3 py-5 rounded-xl border border-primary-4 flex justify-between items-center gap-4">
{/* Image */}
{photo !== undefined ? (
<StrapiImage
data={photo}
className="w-20 h-20 min-w-20 min-h-20 object-cover rounded-full border-primary-2 border-4 shrink-0 grow-0"
displayCaption={false}
/>
) : (
<div className="w-20 h-20 rounded-full bg-primary-4 border-4 border-primary-2 shrink-0 grow-0 flex">
<span className="m-auto text-grey-1 text-3xl font-bold uppercase">
{prenom.slice(0, 1)}
{nom.slice(0, 1)}
</span>
</div>
)}

{/* Contenu */}
<div className="flex flex-col justify-start gap-1 h-full grow">
{/* En-tête */}
<div className="flex justify-between items-start">
{/* Nom */}
<div className="text-primary-9 text-lg font-bold">
{prenom} {nom}
</div>

{/* Liens */}
<div className="flex gap-1 pt-0.5">
{!!linkedin && (
<a
href={
linkedin.startsWith('http') ? linkedin : `https://${linkedin}`
}
target="_blank"
rel="noreferrer noopener"
className="bg-none after:hidden text-primary-5 hover:text-primary-7 transition-colors"
>
<Icon icon="linkedin-box-fill" />
</a>
)}
{!!site && (
<a
href={site.startsWith('http') ? site : `https://${site}`}
target="_blank"
rel="noreferrer noopener"
className="bg-none after:hidden text-primary-5 hover:text-primary-7 transition-colors"
>
<Icon icon="pages-line" />
</a>
)}
</div>
</div>

{/* Détails */}
<div className="flex flex-col gap-1">
{/* Structure */}
<p className="text-primary-7 text-sm font-bold mb-0">{structure}</p>

{/* Région - Ville */}
<p className="text-grey-7 text-xs font-medium mb-0">
{region} - {ville}
</p>

{/* Email */}
<div className="flex gap-1 items-center">
<Tooltip
label={displayCopyMsg ? 'Copié !' : "Copier l'email"}
openingDelay={0}
>
<Icon
icon="file-copy-line"
size="xs"
className="cursor-pointer text-grey-6 hover:text-primary-7 transition-colors"
onClick={() => {
copy(email);
setDisplayCopyMsg(true);
}}
onMouseLeave={() => setDisplayCopyMsg(false)}
/>
</Tooltip>
<a
href={`mailto:${email}`}
className="text-primary-7 text-xs font-medium w-fit bg-none"
>
{email}
</a>
</div>
</div>
</div>
</div>
);
};

export default CarteConseiller;
73 changes: 73 additions & 0 deletions packages/site/app/programme/annuaire/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
'use client';

import Section from '@components/sections/Section';
import CarteConseiller from './CarteConseiller';
import {Input, Pagination} from '@tet/ui';
import {ConseillerType, getData} from './utils';
import {useEffect, useState} from 'react';

const PAGINATION_LIMIT = 12;

const Annuaire = () => {
const [selectedPage, setSelectPage] = useState(1);
const [searchInput, setSearchInput] = useState('');
const [total, setTotal] = useState(0);
const [data, setData] = useState<ConseillerType[]>([]);

const getConseillersData = async () => {
const {data, pagination} = await getData({
page: selectedPage,
limit: PAGINATION_LIMIT,
search: searchInput,
});
setData(data);
setSelectPage(pagination.start / PAGINATION_LIMIT + 1);
setTotal(pagination.total);
};

useEffect(() => {
getConseillersData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedPage, searchInput]);

return (
<Section containerClassName="grow bg-primary-1">
<div className="flex flex-wrap gap-y-6 justify-between items-center mb-6">
<h1 id="annuaire-header" className="text-3xl mb-0">
Annuaire des conseillers-conseillères
</h1>
<Input
className="!w-[435px]"
onChange={evt => setSearchInput(evt.target.value)}
onSearch={() => {}}
type="search"
placeholder="Rechercher un nom, prénom, structure ou région"
/>
</div>

<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-5">
{data.map(carte => (
<CarteConseiller
key={`${carte.prenom}-${carte.nom}-${carte.id}`}
{...carte}
/>
))}
</div>

{total > PAGINATION_LIMIT && (
<div className="flex justify-center mt-8">
<Pagination
selectedPage={selectedPage}
nbOfPages={Math.ceil(total / PAGINATION_LIMIT)}
onChange={selectedPage => {
setSelectPage(selectedPage);
document.getElementById('annuaire-header')?.scrollIntoView();
}}
/>
</div>
)}
</Section>
);
};

export default Annuaire;
55 changes: 55 additions & 0 deletions packages/site/app/programme/annuaire/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {StrapiItem} from 'src/strapi/StrapiItem';
import {fetchCollection} from 'src/strapi/strapi';

export type ConseillerType = {
id: number;
prenom: string;
nom: string;
structure: string;
region: string;
ville: string;
email: string;
linkedin: string;
site: string;
photo: StrapiItem;
};

export const getData = async ({
page,
limit,
search = '',
}: {
page: number;
limit: number;
search?: string;
}) => {
const conseillers = await fetchCollection('conseillers', [
['populate[0]', 'photo'],
['filters[$or][0][prenom][$startsWithi]', search],
['filters[$or][1][nom][$startsWithi]', search],
['filters[$or][2][structure][$startsWithi]', search],
['filters[$or][3][region][$startsWithi]', search],
['sort[0]', 'nom:asc'],
['pagination[start]', `${(page - 1) * limit}`],
['pagination[limit]', `${limit}`],
]);

return {
data: !conseillers.data
? []
: (conseillers.data.map(d => ({
id: d.id,
prenom: d.attributes.prenom as unknown as string,
nom: d.attributes.nom as unknown as string,
structure: d.attributes.structure as unknown as string,
region: d.attributes.region as unknown as string,
ville: d.attributes.ville as unknown as string,
email: d.attributes.email as unknown as string,
linkedin: d.attributes.linkedin as unknown as string,
site: d.attributes.site as unknown as string,
photo:
(d.attributes.photo.data as unknown as StrapiItem) ?? undefined,
})) as ConseillerType[]),
pagination: conseillers.meta.pagination,
};
};
8 changes: 6 additions & 2 deletions packages/site/src/strapi/strapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const headers = {
type Collection =
| 'actualites'
| 'collectivites'
| 'conseillers'
| 'faqs'
| 'services'
| 'temoignages';
Expand All @@ -26,7 +27,10 @@ type Single =
export async function fetchCollection(
path: Collection,
params: [string, string][] = [['populate', '*']],
): Promise<Array<StrapiItem>> {
): Promise<{
data: Array<StrapiItem>;
meta: {pagination: {start: number; limit: number; total: number}};
}> {
const url = new URL(`${baseURL}/api/${path}`);
params.forEach(p => url.searchParams.append(...p));

Expand All @@ -36,7 +40,7 @@ export async function fetchCollection(
headers,
});
const body = await response.json();
return body['data'];
return body;
}

export const fetchSingle = async (
Expand Down
Loading

0 comments on commit 9e2a7b0

Please sign in to comment.