diff --git a/components/MachineCard.css b/components/MachineCard.css
new file mode 100644
index 0000000..896ce67
--- /dev/null
+++ b/components/MachineCard.css
@@ -0,0 +1,56 @@
+.components__machine_card {
+ min-width: 10rem;
+ aspect-ratio: 1 / 2;
+ display: flex;
+ flex-direction: column;
+ padding: var(--_gap-half);
+ gap: var(--_gap);
+ box-shadow: 0 0 0.4rem 0.2rem var(--_translucent);
+ border: var(--_border-size) solid transparent;
+ background-repeat: no-repeat;
+ background-size: contain;
+
+ &:hover:has(a:not(:focus-visible)) {
+ border: var(--_border-size) solid var(--_accent-color);
+ }
+
+ & h3 {
+ margin: 0;
+ }
+}
+
+.components__machine_card__spacer {
+ height: 50%;
+}
+
+.components__machine_card__tags {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--_gap-half);
+
+ & span {
+ padding: var(--_gap-half);
+ background-color: var(--_translucent);
+ }
+}
+
+.components__machine_card__footer {
+ height: fit-content;
+ display: flex;
+ gap: var(--_gap);
+ justify-content: space-between;
+
+ a {
+ width: 100%;
+ padding: var(--_gap);
+ color: currentColor;
+ outline: none;
+ text-decoration: none;
+ border: var(--_border-size) solid currentColor;
+ }
+
+ & a:is(:focus-visible, :hover, :active) {
+ color: var(--_accent-color);
+ border: var(--_border-size) solid var(--_accent-color);
+ }
+}
diff --git a/components/MachineCard.tsx b/components/MachineCard.tsx
new file mode 100644
index 0000000..9a43403
--- /dev/null
+++ b/components/MachineCard.tsx
@@ -0,0 +1,44 @@
+type MachineCardProps = {
+ img: string
+ name: string
+ tags: string[]
+ id: string
+ free: boolean
+}
+
+export function MachineCard(
+ { name, tags, img, id, free }: MachineCardProps,
+) {
+ const stateIcon = free
+ ?
+ :
+
+ return (
+
+
+
+ {stateIcon}
+ {name}
+
+
+ {tags.map((tag) => {tag})}
+
+
+
+ )
+}
+
+export const machineMock: MachineCardProps[] = Array(20).fill(undefined).map(
+ (_, index) => {
+ return {
+ name: `Machine ${index}`,
+ tags: ['3d', 'laser'],
+ free: Math.random() > 0.5,
+ img: `url("https://picsum.photos/id/${index + 10}/400")`,
+ id: String(index),
+ }
+ },
+)
diff --git a/routes/index.tsx b/routes/index.tsx
index 9973fe6..26102d1 100644
--- a/routes/index.tsx
+++ b/routes/index.tsx
@@ -2,6 +2,7 @@ import { Head } from '$fresh/runtime.ts'
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 { SponsorCards } from '../components/SponsorCards.tsx'
export default function Home() {
diff --git a/routes/machines/[id].tsx b/routes/machines/[id].tsx
new file mode 100644
index 0000000..3fd3452
--- /dev/null
+++ b/routes/machines/[id].tsx
@@ -0,0 +1,10 @@
+import { PageProps } from '$fresh/server.ts'
+import { MachineCard, machineMock } from '../../components/MachineCard.tsx'
+
+export default function Machine({ params }: PageProps) {
+ const machine = machineMock.at(Number(params.id))
+
+ return (
+ machine ? MachineCard(machine) : Machine pas encore disponible
+ )
+}
diff --git a/routes/machines/index.tsx b/routes/machines/index.tsx
new file mode 100644
index 0000000..c4131c6
--- /dev/null
+++ b/routes/machines/index.tsx
@@ -0,0 +1,18 @@
+import { MachineCard, machineMock } from '../../components/MachineCard.tsx'
+
+export default function Machine() {
+ return (
+ <>
+ Nos machines
+
+ {machineMock.map(MachineCard)}
+
+ >
+ )
+}
diff --git a/src/stylesheets/components.css b/src/stylesheets/components.css
index 335b48a..518f664 100644
--- a/src/stylesheets/components.css
+++ b/src/stylesheets/components.css
@@ -4,5 +4,6 @@
@import url('../../components/SponsorCards.css');
@import url('../../components/CohabitInfoTable.css');
@import url('../../components/BlogCard.css');
+@import url('../../components/MachineCard.css');
@import url('../../islands/ThemePicker.css');
@import url('../../islands/SearchBox.css');