From 972a84f2415051abe72474468e1c3deefef00a85 Mon Sep 17 00:00:00 2001 From: Julien Oculi Date: Thu, 15 Feb 2024 12:50:40 +0100 Subject: [PATCH] feat: :sparkles: add projects card and routes --- components/ProjectCard.css | 66 ++++++++++++++++++++++++ components/ProjectCard.tsx | 93 ++++++++++++++++++++++++++++++++++ routes/index.tsx | 1 + routes/projets/[id].tsx | 12 +++++ routes/projets/index.tsx | 16 ++++-- src/stylesheets/components.css | 1 + 6 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 components/ProjectCard.css create mode 100644 components/ProjectCard.tsx create mode 100644 routes/projets/[id].tsx diff --git a/components/ProjectCard.css b/components/ProjectCard.css new file mode 100644 index 0000000..e0b05bb --- /dev/null +++ b/components/ProjectCard.css @@ -0,0 +1,66 @@ +.components__project_card { + min-width: 30rem; + aspect-ratio: 2 / 1; + display: grid; + grid-template-columns: 1fr 2fr; + padding: var(--_gap-half); + gap: var(--_gap); + box-shadow: 0 0 0.4rem 0.2rem var(--_translucent); + border: var(--_border-size) solid transparent; + + &:has(a:focus-visible), + &:hover { + border: var(--_border-size) solid var(--_accent-color); + } + + & h3 { + margin: 0; + } + + & a { + outline: none; + text-decoration: none; + background-color: var(--_accent-color); + padding: var(--_gap-half); + color: var(--_background-color); + border: var(--_border-size) solid var(--_accent-color); + + &:hover, + &:focus-visible { + color: var(--_accent-color); + background-color: var(--_background-color); + } + } +} + +.components__project_card__icon { + height: 100%; + object-fit: cover; + overflow: hidden; +} + +.components__project_card__content { + display: flex; + flex-direction: column; +} + +.components__project_card__state { + padding: var(--_gap-half); + font-weight: bold; +} + +.components__project_card__tags { + display: flex; + flex-wrap: wrap; + gap: var(--_gap-half); + + & span { + padding: var(--_gap-half); + background-color: var(--_translucent); + } +} + +.components__project_card__summary { + text-wrap: balance; + flex-grow: 1; +} diff --git a/components/ProjectCard.tsx b/components/ProjectCard.tsx new file mode 100644 index 0000000..3110850 --- /dev/null +++ b/components/ProjectCard.tsx @@ -0,0 +1,93 @@ +import { JSX } from 'preact' + +type ProjectCardProps = { + id: string + icon: string + title: string + summary: string + tags: string[] + state: 'complete' | 'progress' | 'stale' | 'pending' +} + +export function ProjectCard( + { id, icon, title, summary, tags, state }: ProjectCardProps, +) { + return ( +
+ +
+

{title}

+ + {toStateSpan(state)} + +
+ {tags.map((tag) => {tag})} +
+
+ {`${summary.slice(0, 150)} ...`} +
+ + {state === 'complete' ? 'En savoir plus' : 'Participer'} + +
+
+ ) +} + +const summary = + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui, perferendis enim blanditiis consequatur at porro quod, eligendi alias recusandae modi aliquam non? Quos voluptates quisquam provident animi nisi in ratione.' + +export const projectMock: ProjectCardProps[] = Array(50).fill(undefined).map( + (_, index) => { + return { + // + title: `Awesome project ${index}`, + summary, + tags: ['3D', 'électronique', 'informatique'], + state: randomState(), + icon: `https://picsum.photos/id/${index + 20}/300`, + id: String(index), + } + }, +) + +function randomState(): ProjectCardProps['state'] { + const rand = Math.random() + if (rand > 3 / 4) return 'complete' + if (rand > 2 / 4) return 'progress' + if (rand > 1 / 4) return 'stale' + return 'pending' +} + +function toStateSpan(state: ProjectCardProps['state']): JSX.Element { + if (state === 'complete') { + return ( + <> + + {' Terminé'} + + ) + } + if (state === 'pending') { + return ( + <> + + {' Non démarré'} + + ) + } + if (state === 'progress') { + return ( + <> + + {' En cours'} + + ) + } + return ( + <> + + {' En pause'} + + ) +} diff --git a/routes/index.tsx b/routes/index.tsx index 26102d1..d78e90b 100644 --- a/routes/index.tsx +++ b/routes/index.tsx @@ -3,6 +3,7 @@ import { BlogCard, blogMock } from '../components/BlogCard.tsx' import { CohabitInfoTable } from '../components/CohabitInfoTable.tsx' import { Heros } from '../components/Heros.tsx' import { MachineCard, machineMock } from '../components/MachineCard.tsx' +import { ProjectCard, projectMock } from '../components/ProjectCard.tsx' import { SponsorCards } from '../components/SponsorCards.tsx' export default function Home() { diff --git a/routes/projets/[id].tsx b/routes/projets/[id].tsx new file mode 100644 index 0000000..62b12ae --- /dev/null +++ b/routes/projets/[id].tsx @@ -0,0 +1,12 @@ +import { PageProps } from '$fresh/server.ts' +import { ProjectCard, projectMock } from '../../components/ProjectCard.tsx' + +export default function Projets({ params }: PageProps) { + const Projets = projectMock.at(Number(params.id)) + + return ( + Projets + ? ProjectCard(Projets) + :

Projets inconnu, peut être un futur

+ ) +} diff --git a/routes/projets/index.tsx b/routes/projets/index.tsx index 2d10f87..2e9bd0d 100644 --- a/routes/projets/index.tsx +++ b/routes/projets/index.tsx @@ -1,8 +1,18 @@ -export default function Machines() { +import { ProjectCard, projectMock } from '../../components/ProjectCard.tsx' + +export default function Project() { return ( <> -

Nos projets

-
+

Nos Projets

+
+ {projectMock.map(ProjectCard)} +
) } diff --git a/src/stylesheets/components.css b/src/stylesheets/components.css index 518f664..1337eb9 100644 --- a/src/stylesheets/components.css +++ b/src/stylesheets/components.css @@ -5,5 +5,6 @@ @import url('../../components/CohabitInfoTable.css'); @import url('../../components/BlogCard.css'); @import url('../../components/MachineCard.css'); +@import url('../../components/ProjectCard.css'); @import url('../../islands/ThemePicker.css'); @import url('../../islands/SearchBox.css');