diff --git a/backend/src/api/about/content-types/about/schema.json b/backend/src/api/about/content-types/about/schema.json index 48d1d160..b5fdd1ff 100644 --- a/backend/src/api/about/content-types/about/schema.json +++ b/backend/src/api/about/content-types/about/schema.json @@ -74,6 +74,11 @@ "type": "relation", "relation": "oneToMany", "target": "api::volunteer.volunteer" + }, + "activity_reports": { + "type": "component", + "component": "file-list-with-dates.file-with-date", + "repeatable": true } } } diff --git a/backend/src/components/file-list-with-dates/file-with-date.json b/backend/src/components/file-list-with-dates/file-with-date.json new file mode 100644 index 00000000..e23a1925 --- /dev/null +++ b/backend/src/components/file-list-with-dates/file-with-date.json @@ -0,0 +1,26 @@ +{ + "collectionName": "components_file_list_with_dates_file_with_dates", + "info": { + "displayName": "File-with-date", + "icon": "filePdf" + }, + "options": {}, + "attributes": { + "date": { + "type": "date", + "required": true + }, + "file": { + "type": "media", + "multiple": false, + "required": true, + "allowedTypes": [ + "images", + "files", + "videos", + "audios" + ] + } + }, + "config": {} +} diff --git a/backend/src/extensions/documentation/documentation/1.0.0/full_documentation.json b/backend/src/extensions/documentation/documentation/1.0.0/full_documentation.json index 03adfad1..b6cce2a0 100644 --- a/backend/src/extensions/documentation/documentation/1.0.0/full_documentation.json +++ b/backend/src/extensions/documentation/documentation/1.0.0/full_documentation.json @@ -14,7 +14,7 @@ "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html" }, - "x-generation-date": "2025-10-01T08:09:20.342Z" + "x-generation-date": "2026-02-27T11:12:11.224Z" }, "x-strapi-config": { "plugins": [ @@ -12524,6 +12524,12 @@ "example": "string or id" } }, + "activity_reports": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FileListWithDatesFileWithDateComponent" + } + }, "locale": { "type": "string" }, @@ -15083,6 +15089,12 @@ } } }, + "activity_reports": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FileListWithDatesFileWithDateComponent" + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -15239,6 +15251,12 @@ } } }, + "activity_reports": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FileListWithDatesFileWithDateComponent" + } + }, "createdAt": { "type": "string", "format": "date-time" @@ -15764,6 +15782,147 @@ } } }, + "FileListWithDatesFileWithDateComponent": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "date": { + "type": "string", + "format": "date" + }, + "file": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + }, + "name": { + "type": "string" + }, + "alternativeText": { + "type": "string" + }, + "caption": { + "type": "string" + }, + "width": { + "type": "integer" + }, + "height": { + "type": "integer" + }, + "formats": {}, + "hash": { + "type": "string" + }, + "ext": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "size": { + "type": "number", + "format": "float" + }, + "url": { + "type": "string" + }, + "previewUrl": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "provider_metadata": {}, + "related": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + }, + "folder": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "folderPath": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "publishedAt": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "updatedBy": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + }, + "locale": { + "type": "string" + }, + "localizations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "documentId": { + "type": "string" + } + } + } + } + } + } + } + }, "KpiKpiComponent": { "type": "object", "properties": { diff --git a/backend/types/generated/components.d.ts b/backend/types/generated/components.d.ts index 4638836a..dcd1d134 100644 --- a/backend/types/generated/components.d.ts +++ b/backend/types/generated/components.d.ts @@ -40,6 +40,19 @@ export interface EditoEdito extends Struct.ComponentSchema { }; } +export interface FileListWithDatesFileWithDate extends Struct.ComponentSchema { + collectionName: 'components_file_list_with_dates_file_with_dates'; + info: { + displayName: 'File-with-date'; + icon: 'filePdf'; + }; + attributes: { + date: Schema.Attribute.Date & Schema.Attribute.Required; + file: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios'> & + Schema.Attribute.Required; + }; +} + export interface GoalGoal extends Struct.ComponentSchema { collectionName: 'components_goal_goals'; info: { @@ -157,6 +170,7 @@ declare module '@strapi/strapi' { 'call-to-action.call-to-action': CallToActionCallToAction; 'call-to-action.call-to-action-with-image': CallToActionCallToActionWithImage; 'edito.edito': EditoEdito; + 'file-list-with-dates.file-with-date': FileListWithDatesFileWithDate; 'goal.goal': GoalGoal; 'hero.hero': HeroHero; 'information.information-block': InformationInformationBlock; diff --git a/backend/types/generated/contentTypes.d.ts b/backend/types/generated/contentTypes.d.ts index e4a5a042..e1c0154f 100644 --- a/backend/types/generated/contentTypes.d.ts +++ b/backend/types/generated/contentTypes.d.ts @@ -385,6 +385,10 @@ export interface ApiAboutAbout extends Struct.SingleTypeSchema { draftAndPublish: true; }; attributes: { + activity_reports: Schema.Attribute.Component< + 'file-list-with-dates.file-with-date', + true + >; board_of_directors: Schema.Attribute.Relation< 'oneToMany', 'api::volunteer.volunteer' diff --git a/frontend/src/app/[locale]/about/about.tsx b/frontend/src/app/[locale]/about/about.tsx index 857a5ed3..7e0efb6a 100644 --- a/frontend/src/app/[locale]/about/about.tsx +++ b/frontend/src/app/[locale]/about/about.tsx @@ -9,6 +9,7 @@ import { PartnersBlock, Title, TestimoniesCarousel, + CtaList, } from '@/components'; import { IMembers } from '@/lib/types'; import { AboutPageData } from './page'; @@ -84,6 +85,16 @@ function transformMembers({ ]; } +function transformActivityReports( + reports: NonNullable +) { + return reports.map(report => ({ + id: report.documentId || report.id, + text: new Date(report.date).getFullYear().toString(), + link: report.file?.url || '#', + })); +} + type AboutProps = { data: AboutPageData; }; @@ -100,6 +111,9 @@ export default function AboutPage({ data }: AboutProps) { strategic_committee: data.strategic_committee, division_managers: data.division_managers, }); + const activityReports = data.activity_reports + ? transformActivityReports(data.activity_reports) + : []; return ( <> @@ -198,6 +212,15 @@ export default function AboutPage({ data }: AboutProps) { categories={members} className="my-lg" /> + + {activityReports.length > 0 && ( +
+ + Rapports d'activités + + +
+ )} ); } diff --git a/frontend/src/app/[locale]/about/page.tsx b/frontend/src/app/[locale]/about/page.tsx index 9c7382d2..2ca9e4d5 100644 --- a/frontend/src/app/[locale]/about/page.tsx +++ b/frontend/src/app/[locale]/about/page.tsx @@ -1,7 +1,6 @@ -import React from 'react'; -import AboutPage from './about'; import client from '@/lib/strapi-client'; import { generateMetadataFromSeo } from '@/lib/utils'; +import AboutPage from './about'; export async function generateMetadata({ params: { locale }, @@ -49,15 +48,22 @@ async function fetchAboutPageData() { scientific_committee: { populate: "*" }, - strategic_committee: { - populate: "*" - }, - division_managers: { - populate: "*" - }, - seo_meta: { - populate: "*" - } + strategic_committee: { + populate: "*" + }, + division_managers: { + populate: "*" + }, + seo_meta: { + populate: "*" + }, + activity_reports: { + populate: { + file: { + populate: '*' + } + } + } } } } @@ -68,9 +74,10 @@ export type AboutPageData = NonNullable & { - direction?: 'up' | 'down' | 'left' | 'right'; + direction?: 'up' | 'down' | 'left' | 'right' | 'download'; className?: string; }; @@ -16,13 +16,14 @@ const ArrowIcon: React.FC = ({ down: 'rotate-90', left: 'rotate-180', right: 'rotate-0', + download: 'rotate-0', }; return ( = ({ )} {...props} > - + {direction === 'download' ? ( + + ) : ( + + )} ); }; diff --git a/frontend/src/components/molecules/CtaList/CtaList.tsx b/frontend/src/components/molecules/CtaList/CtaList.tsx new file mode 100644 index 00000000..8742be04 --- /dev/null +++ b/frontend/src/components/molecules/CtaList/CtaList.tsx @@ -0,0 +1,39 @@ +'use client'; + +import clsx from 'clsx'; +import Link from 'next/link'; +import { ArrowIcon } from '@/components'; + +export type CtaListItem = { + id: string | number; + text: string; + link: string; +}; + +export type CtaListProps = { + items: CtaListItem[]; + className?: string; +}; + +const CtaList: React.FC = ({ items, className }) => { + return ( +
+ {items.map((item) => ( + +
+ + {item.text} + + +
+ + ))} +
+ ); +}; + +export default CtaList; diff --git a/frontend/src/components/molecules/index.ts b/frontend/src/components/molecules/index.ts index 4509d424..80b36574 100644 --- a/frontend/src/components/molecules/index.ts +++ b/frontend/src/components/molecules/index.ts @@ -52,3 +52,6 @@ export type { LargeTextImageDonationProps } from './LargeTextImageDonation/Large export { default as CampaignBanner } from './CampaignBanner/CampaignBanner'; export type { CampaignBannerProps } from './CampaignBanner/CampaignBanner'; + +export { default as CtaList } from './CtaList/CtaList'; +export type { CtaListProps, CtaListItem } from './CtaList/CtaList'; diff --git a/frontend/src/types/strapi/generated/components.d.ts b/frontend/src/types/strapi/generated/components.d.ts index 4638836a..dcd1d134 100644 --- a/frontend/src/types/strapi/generated/components.d.ts +++ b/frontend/src/types/strapi/generated/components.d.ts @@ -40,6 +40,19 @@ export interface EditoEdito extends Struct.ComponentSchema { }; } +export interface FileListWithDatesFileWithDate extends Struct.ComponentSchema { + collectionName: 'components_file_list_with_dates_file_with_dates'; + info: { + displayName: 'File-with-date'; + icon: 'filePdf'; + }; + attributes: { + date: Schema.Attribute.Date & Schema.Attribute.Required; + file: Schema.Attribute.Media<'images' | 'files' | 'videos' | 'audios'> & + Schema.Attribute.Required; + }; +} + export interface GoalGoal extends Struct.ComponentSchema { collectionName: 'components_goal_goals'; info: { @@ -157,6 +170,7 @@ declare module '@strapi/strapi' { 'call-to-action.call-to-action': CallToActionCallToAction; 'call-to-action.call-to-action-with-image': CallToActionCallToActionWithImage; 'edito.edito': EditoEdito; + 'file-list-with-dates.file-with-date': FileListWithDatesFileWithDate; 'goal.goal': GoalGoal; 'hero.hero': HeroHero; 'information.information-block': InformationInformationBlock; diff --git a/frontend/src/types/strapi/generated/contentTypes.d.ts b/frontend/src/types/strapi/generated/contentTypes.d.ts index e4a5a042..e1c0154f 100644 --- a/frontend/src/types/strapi/generated/contentTypes.d.ts +++ b/frontend/src/types/strapi/generated/contentTypes.d.ts @@ -385,6 +385,10 @@ export interface ApiAboutAbout extends Struct.SingleTypeSchema { draftAndPublish: true; }; attributes: { + activity_reports: Schema.Attribute.Component< + 'file-list-with-dates.file-with-date', + true + >; board_of_directors: Schema.Attribute.Relation< 'oneToMany', 'api::volunteer.volunteer'