Refactoring

This commit is contained in:
Rampeur
2025-08-07 09:00:42 +02:00
parent 2a3a03dd31
commit 3ce58faa1c
11 changed files with 400 additions and 300 deletions
+12 -1
View File
@@ -1,3 +1,14 @@
{ {
"extends": "next/core-web-vitals" "extends": ["next/core-web-vitals", "next/typescript", "prettier"],
"rules": {
"@typescript-eslint/no-unused-vars": [
"warn",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_",
"destructuredArrayIgnorePattern": "^_"
}
]
}
} }
+13
View File
@@ -28,6 +28,7 @@
"@types/react-dom": "^19.1.7", "@types/react-dom": "^19.1.7",
"eslint": "^9.32.0", "eslint": "^9.32.0",
"eslint-config-next": "^15.4.5", "eslint-config-next": "^15.4.5",
"eslint-config-prettier": "^9.1.0",
"husky": "^9.1.6", "husky": "^9.1.6",
"lint-staged": "^15.2.10", "lint-staged": "^15.2.10",
"openapi-typescript": "^7.4.1", "openapi-typescript": "^7.4.1",
@@ -3134,6 +3135,18 @@
} }
} }
}, },
"node_modules/eslint-config-prettier": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz",
"integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==",
"dev": true,
"bin": {
"eslint-config-prettier": "bin/cli.js"
},
"peerDependencies": {
"eslint": ">=7.0.0"
}
},
"node_modules/eslint-import-resolver-node": { "node_modules/eslint-import-resolver-node": {
"version": "0.3.9", "version": "0.3.9",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
+1
View File
@@ -37,6 +37,7 @@
"@types/react-dom": "^19.1.7", "@types/react-dom": "^19.1.7",
"eslint": "^9.32.0", "eslint": "^9.32.0",
"eslint-config-next": "^15.4.5", "eslint-config-next": "^15.4.5",
"eslint-config-prettier": "^9.1.0",
"husky": "^9.1.6", "husky": "^9.1.6",
"lint-staged": "^15.2.10", "lint-staged": "^15.2.10",
"openapi-typescript": "^7.4.1", "openapi-typescript": "^7.4.1",
+168 -158
View File
@@ -1,174 +1,184 @@
"use client"; "use client";
import React, { useEffect } from 'react'; import React, { useEffect } from "react";
const TimeClock: React.FC = () => { const TimeClock: React.FC = () => {
useEffect(() => { useEffect(() => {
const numbers = [
[1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1], // 0
[1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1], // 1
[1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1], // 2
[1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1], // 3
[1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1], // 4
[1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1], // 5
[1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1], // 6
[1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0], // 7
[1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1], // 8
[1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1], // 9
];
const numbers = [ const blocks: Array<Element[]> = [];
[1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1], // 0 const digits = Array.from(document.querySelectorAll(".block"));
[1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1], // 1
[1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1], // 2
[1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1], // 3
[1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1], // 4
[1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1], // 5
[1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1], // 6
[1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0], // 7
[1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1], // 8
[1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1] // 9
];
const blocks: Array<Element[]> = []; for (let i = 0; i < 4; i++) {
const digits = Array.from(document.querySelectorAll('.block')); blocks.push(digits.slice(i * 15, i * 15 + 15));
}
for (let i = 0; i < 4; i++) { const setNum = (block: Array<Element>, num: number) => {
blocks.push(digits.slice(i * 15, i * 15 + 15)); const n = numbers[num];
for (let i = 0; i < block.length; i++) {
block[i].classList[n[i] === 1 ? "add" : "remove"]("active");
}
};
const time = {
s: "",
m: "",
h: "",
p: 0,
};
// time loop
const animator = () => {
const d = new Date();
let h = d.getHours().toString(),
m = d.getMinutes().toString(),
s = d.getSeconds().toString();
s = s.length === 1 ? "0" + s : s;
m = m.length === 1 ? "0" + m : m;
h = h.length === 1 ? "0" + h : h;
if (s !== time.s) {
for (let i = 0; i < digits.length; i++) {
const d = digits[i];
if (i === +s) {
d.classList.add("second");
if (time.p !== null) digits[time.p].classList.remove("second");
time.p = i;
time.s = s;
}
} }
}
const setNum = (block: Array<Element>, num: number) => { if (m !== time.m) {
let n = numbers[num]; setNum(blocks[2], parseInt(Array.from(m)[0]));
for (let i = 0; i < block.length; i++) { setNum(blocks[3], parseInt(Array.from(m)[1]));
block[i].classList[n[i] === 1 ? 'add' : 'remove']('active'); time.m = m;
} }
};
const time = { if (h !== time.h) {
s: '', setNum(blocks[0], parseInt(Array.from(h)[0]));
m: '', setNum(blocks[1], parseInt(Array.from(h)[1]));
h: '', time.h = h;
p: 0 }
}; window.requestAnimationFrame(animator);
};
// time loop // init
const animator = () => { window.requestAnimationFrame(animator);
let d = new Date(),
h = d.getHours().toString(),
m = d.getMinutes().toString(),
s = d.getSeconds().toString();
s = s.length === 1 ? '0' + s : s; // toggle button
m = m.length === 1 ? '0' + m : m; const d = new Date();
h = h.length === 1 ? '0' + h : h; const days = ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"];
const months = [
"Janvier",
"Février",
"Mars",
"Avril",
"Mai",
"Juin",
"Juillet",
"Août",
"Septembre",
"Octobre",
"Novembre",
"Décembre",
];
const lib_d = days[d.getDay()];
const lib_m = months[d.getMonth()];
const lib_n = d.getDate();
const lib_y = d.getFullYear();
document.getElementById("datelib")!.innerHTML = lib_d + " " + lib_n + " " + lib_m + " " + lib_y;
}, []);
if (s !== time.s) { return (
for (let i = 0; i < digits.length; i++) { <>
let d = digits[i]; <div className="date d-flex mb-2 pt-2">
if (i === +s) { <div className="flex-grow-1"></div>
d.classList.add('second'); <div className="datelib mt-2 pt-1 ps-1 font-monospace opacity-50 fs-5">
if (time.p !== null) <span className="icon-calendar me-2" aria-hidden="true"></span>
digits[time.p].classList.remove('second'); <span id="datelib"></span>
time.p = i; </div>
time.s = s; </div>
} <div className="time d-flex">
} <div className="flex-grow-1"></div>
} <div className="clock position-relative d-flex flex-column flex-wrap">
<div className="block" data-num="0"></div>
if (m !== time.m) { <div className="block" data-num="1"></div>
setNum(blocks[2], parseInt(Array.from(m)[0])); <div className="block" data-num="2"></div>
setNum(blocks[3], parseInt(Array.from(m)[1])); <div className="block" data-num="3"></div>
time.m = m; <div className="block" data-num="4"></div>
} <div className="block" data-num="5"></div>
<div className="block" data-num="6"></div>
if (h !== time.h) { <div className="block" data-num="7"></div>
setNum(blocks[0], parseInt(Array.from(h)[0])); <div className="block" data-num="8"></div>
setNum(blocks[1], parseInt(Array.from(h)[1])); <div className="block" data-num="9"></div>
time.h = h; <div className="block" data-num="10"></div>
} <div className="block" data-num="11"></div>
window.requestAnimationFrame(animator) <div className="block" data-num="12"></div>
} <div className="block" data-num="13"></div>
<div className="block" data-num="14"></div>
// init <div className="block" data-num="15"></div>
window.requestAnimationFrame(animator) <div className="block" data-num="16"></div>
<div className="block" data-num="17"></div>
// toggle button <div className="block" data-num="18"></div>
var d = new Date(); <div className="block" data-num="19"></div>
var days = ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"]; <div className="block" data-num="20"></div>
var months = ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"]; <div className="block" data-num="21"></div>
var lib_d = days[d.getDay()]; <div className="block" data-num="22"></div>
var lib_m = months[d.getMonth()]; <div className="block" data-num="23"></div>
var lib_n = d.getDate(); <div className="block" data-num="24"></div>
var lib_y = d.getFullYear(); <div className="block" data-num="25"></div>
document.getElementById("datelib")!.innerHTML = lib_d + " " + lib_n + " " + lib_m + " " + lib_y; <div className="block" data-num="26"></div>
<div className="block" data-num="27"></div>
}, []); <div className="block" data-num="28"></div>
<div className="block" data-num="29"></div>
return ( <div className="block" data-num="30"></div>
<> <div className="block" data-num="31"></div>
<div className="date d-flex mb-2 pt-2"> <div className="block" data-num="32"></div>
<div className="flex-grow-1"></div> <div className="block" data-num="33"></div>
<div className="datelib mt-2 pt-1 ps-1 font-monospace opacity-50 fs-5"> <div className="block" data-num="34"></div>
<span className="icon-calendar me-2" aria-hidden="true"></span> <div className="block" data-num="35"></div>
<span id="datelib"></span> <div className="block" data-num="36"></div>
</div> <div className="block" data-num="37"></div>
</div> <div className="block" data-num="38"></div>
<div className="time d-flex"> <div className="block" data-num="39"></div>
<div className="flex-grow-1"></div> <div className="block" data-num="40"></div>
<div className="clock position-relative d-flex flex-column flex-wrap"> <div className="block" data-num="41"></div>
<div className="block" data-num="0"></div> <div className="block" data-num="42"></div>
<div className="block" data-num="1"></div> <div className="block" data-num="43"></div>
<div className="block" data-num="2"></div> <div className="block" data-num="44"></div>
<div className="block" data-num="3"></div> <div className="block" data-num="45"></div>
<div className="block" data-num="4"></div> <div className="block" data-num="46"></div>
<div className="block" data-num="5"></div> <div className="block" data-num="47"></div>
<div className="block" data-num="6"></div> <div className="block" data-num="48"></div>
<div className="block" data-num="7"></div> <div className="block" data-num="49"></div>
<div className="block" data-num="8"></div> <div className="block" data-num="50"></div>
<div className="block" data-num="9"></div> <div className="block" data-num="51"></div>
<div className="block" data-num="10"></div> <div className="block" data-num="52"></div>
<div className="block" data-num="11"></div> <div className="block" data-num="53"></div>
<div className="block" data-num="12"></div> <div className="block" data-num="54"></div>
<div className="block" data-num="13"></div> <div className="block" data-num="55"></div>
<div className="block" data-num="14"></div> <div className="block" data-num="56"></div>
<div className="block" data-num="15"></div> <div className="block" data-num="57"></div>
<div className="block" data-num="16"></div> <div className="block" data-num="58"></div>
<div className="block" data-num="17"></div> <div className="block" data-num="59"></div>
<div className="block" data-num="18"></div> <div className="divider position-absolute"></div>
<div className="block" data-num="19"></div> </div>
<div className="block" data-num="20"></div> </div>
<div className="block" data-num="21"></div> </>
<div className="block" data-num="22"></div> );
<div className="block" data-num="23"></div>
<div className="block" data-num="24"></div>
<div className="block" data-num="25"></div>
<div className="block" data-num="26"></div>
<div className="block" data-num="27"></div>
<div className="block" data-num="28"></div>
<div className="block" data-num="29"></div>
<div className="block" data-num="30"></div>
<div className="block" data-num="31"></div>
<div className="block" data-num="32"></div>
<div className="block" data-num="33"></div>
<div className="block" data-num="34"></div>
<div className="block" data-num="35"></div>
<div className="block" data-num="36"></div>
<div className="block" data-num="37"></div>
<div className="block" data-num="38"></div>
<div className="block" data-num="39"></div>
<div className="block" data-num="40"></div>
<div className="block" data-num="41"></div>
<div className="block" data-num="42"></div>
<div className="block" data-num="43"></div>
<div className="block" data-num="44"></div>
<div className="block" data-num="45"></div>
<div className="block" data-num="46"></div>
<div className="block" data-num="47"></div>
<div className="block" data-num="48"></div>
<div className="block" data-num="49"></div>
<div className="block" data-num="50"></div>
<div className="block" data-num="51"></div>
<div className="block" data-num="52"></div>
<div className="block" data-num="53"></div>
<div className="block" data-num="54"></div>
<div className="block" data-num="55"></div>
<div className="block" data-num="56"></div>
<div className="block" data-num="57"></div>
<div className="block" data-num="58"></div>
<div className="block" data-num="59"></div>
<div className="divider position-absolute"></div>
</div>
</div>
</>
);
}; };
export default TimeClock; export default TimeClock;
@@ -7,6 +7,7 @@ import { convertMarkdownToHtml } from "@/modules/features/article/functions";
import { FollowButton } from "@/modules/features/profile/components/followButton"; import { FollowButton } from "@/modules/features/profile/components/followButton";
import { Article, User } from "@/utils/types/models"; import { Article, User } from "@/utils/types/models";
import Link from "next/link"; import Link from "next/link";
import Image from "next/image";
import { ReactNode } from "react"; import { ReactNode } from "react";
import styles from "./articleArea.module.css"; import styles from "./articleArea.module.css";
import { showDeleteArticleButton, showEditArticleButton, showFollowButton } from "./functions"; import { showDeleteArticleButton, showEditArticleButton, showFollowButton } from "./functions";
@@ -18,7 +19,7 @@ const Actions = ({ article, currentUser }: { article: Article; currentUser?: Use
return ( return (
<div className="article-meta"> <div className="article-meta">
<Link href={`/profile/${profile.username}`}>{profile.image && <img src={profile.image} alt="" />}</Link> <Link href={`/profile/${profile.username}`}>{profile.image && <Image src={profile.image} alt="" />}</Link>
<div className="info"> <div className="info">
<Link href={`/profile/${profile.username}`} className="author"> <Link href={`/profile/${profile.username}`} className="author">
{profile.username} {profile.username}
@@ -1,5 +1,6 @@
import { Comment } from "@/utils/types/models";
import Link from "next/link"; import Link from "next/link";
import Image from "next/image";
import { Comment } from "@/utils/types/models";
import styles from "./presentation.module.css"; import styles from "./presentation.module.css";
type Props = { type Props = {
@@ -17,7 +18,7 @@ export const CommentCard = ({ comment, showDeleteCommentButton, deleteCommentAct
</div> </div>
<div className="card-footer"> <div className="card-footer">
<Link href={`/profile/${comment.author.username}`} className="comment-author"> <Link href={`/profile/${comment.author.username}`} className="comment-author">
{comment.author.image && <img src={comment.author.image} className="comment-author-img" alt="" />} {comment.author.image && <Image src={comment.author.image} className="comment-author-img" alt="" />}
</Link> </Link>
&nbsp; &nbsp;
<Link href={`/profile/${comment.author.username}`} className="comment-author"> <Link href={`/profile/${comment.author.username}`} className="comment-author">
@@ -1,3 +1,4 @@
import Image from "next/image";
import { Button } from "@/modules/common/components/button"; import { Button } from "@/modules/common/components/button";
import { ErrorMessage } from "@/modules/common/components/errorMessage"; import { ErrorMessage } from "@/modules/common/components/errorMessage";
import { SubmissionResult, useForm } from "@conform-to/react"; import { SubmissionResult, useForm } from "@conform-to/react";
@@ -51,7 +52,7 @@ export const CommentForm = ({ slug, authorImage, result, postCommentAction, isPe
<ErrorMessage messages={errors} /> <ErrorMessage messages={errors} />
</div> </div>
<div className="card-footer"> <div className="card-footer">
{authorImage && <img src={authorImage} alt="" className="comment-author-img" />} {authorImage && <Image src={authorImage} alt="" className="comment-author-img" />}
<Button component="button" type="submit" disabled={isPending}> <Button component="button" type="submit" disabled={isPending}>
Post Comment Post Comment
</Button> </Button>
+68 -70
View File
@@ -12,80 +12,78 @@ import { SearchParams } from "./_types";
import TimeClock from "./_components/timeClock/timeClock"; import TimeClock from "./_components/timeClock/timeClock";
const ArticleList = (searchParams: SearchParams) => { const ArticleList = (searchParams: SearchParams) => {
switch (searchParams.tab) { switch (searchParams.tab) {
case "yours": case "yours":
return <FeedArticleList currentPage={searchParams.page} />; return <FeedArticleList currentPage={searchParams.page} />;
case "global": case "global":
return <GlobalArticleList currentPage={searchParams.page} />; return <GlobalArticleList currentPage={searchParams.page} />;
case "tag": case "tag":
return <TagArticleList currentPage={searchParams.page} tag={searchParams.tag ?? ""} />; return <TagArticleList currentPage={searchParams.page} tag={searchParams.tag ?? ""} />;
default: default:
throw new ExhaustiveError(searchParams.tab, "all tab cases are not covered"); throw new ExhaustiveError(searchParams.tab, "all tab cases are not covered");
} }
}; };
const Page = async (props: { searchParams: Promise<{ [key: string]: string | string[] | undefined }> }) => { const Page = async (props: { searchParams: Promise<{ [key: string]: string | string[] | undefined }> }) => {
const session = await getSession(); const session = await getSession();
const searchParams = SearchParams.parse(await props.searchParams); const searchParams = SearchParams.parse(await props.searchParams);
return ( return (
<div className="home-page h-100"> <div className="home-page h-100">
<Container className="banner"> <Container className="banner">
<Row> <Row>
<Col sm={6} md={7} lg={8}> <Col sm={6} md={7} lg={8}>
<h1 className="mt-4">Ad Astra, bientôt en ligne!</h1> <h1 className="mt-4">Ad Astra, bientôt en ligne!</h1>
<p className="fs-4"> <p className="fs-4">Encore un peu de patience, notre site sera disponible d&apos;ici peu.</p>
Encore un peu de patience, notre site sera disponible d'ici peu. </Col>
</p> <Col sm={6} md={5} lg={4}>
</Col> <TimeClock />
<Col sm={6} md={5} lg={4}> </Col>
<TimeClock /> </Row>
</Col> </Container>
</Row> <Container className="page">
</Container> <hr className="col-1 my-5 mx-0" />
<Container className="page"> <Row>
<hr className="col-1 my-5 mx-0" /> <Col md={9}>
<Row> <div className="feed-toggle">
<Col md={9}> <ul className="nav nav-pills outline-active">
<div className="feed-toggle"> {session && (
<ul className="nav nav-pills outline-active"> <li className="nav-item">
{session && ( <Link className={clsx("nav-link", searchParams.tab === "yours" && "active")} href="/?tab=yours">
<li className="nav-item"> Your Feed
<Link className={clsx("nav-link", searchParams.tab === "yours" && "active")} href="/?tab=yours"> </Link>
Your Feed </li>
</Link> )}
</li> <li className="nav-item">
)} <Link className={clsx("nav-link", searchParams.tab === "global" && "active")} href="/?tab=global">
<li className="nav-item"> Global Feed
<Link className={clsx("nav-link", searchParams.tab === "global" && "active")} href="/?tab=global"> </Link>
Global Feed </li>
</Link> {searchParams.tag && (
</li> <li className="nav-item">
{searchParams.tag && ( <Link
<li className="nav-item"> className={clsx("nav-link", searchParams.tab === "tag" && "active")}
<Link href={`/?tab=tag&tag=${searchParams.tag}`}
className={clsx("nav-link", searchParams.tab === "tag" && "active")} >
href={`/?tab=tag&tag=${searchParams.tag}`} #{searchParams.tag}
> </Link>
#{searchParams.tag} </li>
</Link> )}
</li> </ul>
)} </div>
</ul> <Suspense key={JSON.stringify(searchParams)} fallback={<p>Chargement...</p>}>
</div> <ArticleList {...searchParams} />
<Suspense key={JSON.stringify(searchParams)} fallback={<p>Chargement...</p>}> </Suspense>
<ArticleList {...searchParams} /> </Col>
</Suspense> <Col md={3}>
</Col> <Suspense fallback={<p>Chargement...</p>}>
<Col md={3}> <TagList />
<Suspense fallback={<p>Chargement...</p>}> </Suspense>
<TagList /> </Col>
</Suspense> </Row>
</Col> </Container>
</Row> </div>
</Container> );
</div>
);
}; };
export default Page; export default Page;
+3 -2
View File
@@ -1,9 +1,10 @@
import { ReactNode } from "react";
import Image from "next/image";
import { Button } from "@/modules/common/components/button"; import { Button } from "@/modules/common/components/button";
import { fetchCurrentUser } from "@/modules/features/auth/fetch/fetchCurrentUser"; import { fetchCurrentUser } from "@/modules/features/auth/fetch/fetchCurrentUser";
import { FollowButton } from "@/modules/features/profile/components/followButton"; import { FollowButton } from "@/modules/features/profile/components/followButton";
import { fetchProfile } from "@/modules/features/profile/fetch/fetchProfile"; import { fetchProfile } from "@/modules/features/profile/fetch/fetchProfile";
import { getSession } from "@/utils/auth/session"; import { getSession } from "@/utils/auth/session";
import { ReactNode } from "react";
import { showEditProfileSettingsButton, showFollowButton } from "./_functions"; import { showEditProfileSettingsButton, showFollowButton } from "./_functions";
type Props = { type Props = {
@@ -23,7 +24,7 @@ const Layout = async ({ children, params }: Props) => {
<div className="container"> <div className="container">
<div className="row"> <div className="row">
<div className="col-xs-12 col-md-10 offset-md-1"> <div className="col-xs-12 col-md-10 offset-md-1">
{profile.image && <img src={profile.image} className="user-img" alt="" />} {profile.image && <Image src={profile.image} className="user-img" alt="" />}
<h4>{profile.username}</h4> <h4>{profile.username}</h4>
{profile.bio && <p>{profile.bio}</p>} {profile.bio && <p>{profile.bio}</p>}
{showFollowButton(profile.username, currentUser) && <FollowButton {...profile} color="secondary" />} {showFollowButton(profile.username, currentUser) && <FollowButton {...profile} color="secondary" />}
+125 -63
View File
@@ -1,68 +1,130 @@
import Link from "next/link"; import Link from "next/link";
import LogoSmall from "@/app/_components/layoutElements/logoSmall"; import LogoSmall from "@/app/_components/layoutElements/logoSmall";
import { ComponentPropsWithoutRef } from "react"; //import { ComponentPropsWithoutRef } from "react";
type Props = ComponentPropsWithoutRef<"footer">; //type Props = ComponentPropsWithoutRef<"footer">;
export const Footer = (props: Props) => ( export const Footer = () => (
<footer className="bd-footer pt-3 pb-2 pt-md-4 mt-5 bg-blue-gold"> <footer className="bd-footer pt-3 pb-2 pt-md-4 mt-5 bg-blue-gold">
<div className="container py-4 py-md-5 px-4 px-md-3 text-body-secondary"> <div className="container py-4 py-md-5 px-4 px-md-3 text-body-secondary">
<div className="row"> <div className="row">
<div className="col-lg-3 mb-3"> <div className="col-lg-3 mb-3">
<Link className="d-inline-flex align-items-center mb-2 text-body-emphasis text-decoration-none" href="/" aria-label="Bootstrap"> <Link
<LogoSmall /> className="d-inline-flex align-items-center mb-2 text-body-emphasis text-decoration-none"
</Link> href="/"
<ul className="list-unstyled small"> aria-label="Bootstrap"
<li className="mb-2"> >
L'équipe de passionnés Ad Astra est réactive et à l'écoute de vos demandes afin de vous accompagner au mieux et satisfaire vos besoins en fleurs et hashes CBD de qualité. <LogoSmall />
</li> </Link>
<li className="mb-2"> <ul className="list-unstyled small">
Exigez la qualité Ad Astra, vous la méritez. <li className="mb-2">
</li> L&apos;équipe de passionnés Ad Astra est réactive et à l&apos;écoute de vos demandes afin de vous
</ul> accompagner au mieux et satisfaire vos besoins en fleurs et hashes CBD de qualité.
</div> </li>
<div className="col-6 col-lg-2 offset-lg-1 mb-3"> <li className="mb-2">Exigez la qualité Ad Astra, vous la méritez.</li>
<h5>Nos produits</h5> </ul>
<ul className="list-unstyled"> </div>
<li className="mb-2"><Link href="/">Accueil</Link></li> <div className="col-6 col-lg-2 offset-lg-1 mb-3">
<li className="mb-2"><Link href="/produits/fleurs">Lien 2</Link></li> <h5>Nos produits</h5>
<li className="mb-2"><Link href="/produits/resines">Lien 3</Link></li> <ul className="list-unstyled">
<li className="mb-2"><Link href="/produits/molecules">Lien 4</Link></li> <li className="mb-2">
<li className="mb-2"><Link href="/produits/concentres">Lien 5</Link></li> <Link href="/">Accueil</Link>
</ul> </li>
</div> <li className="mb-2">
<div className="col-6 col-lg-2 mb-3"> <Link href="/produits/fleurs">Lien 2</Link>
<h5>Documentation</h5> </li>
<ul className="list-unstyled"> <li className="mb-2">
<li className="mb-2"><Link href="/fleurs">Les fleurs</Link></li> <Link href="/produits/resines">Lien 3</Link>
<li className="mb-2"><Link href="/resines">Les hashes</Link></li> </li>
<li className="mb-2"><Link href="/molecules">Les molécules</Link></li> <li className="mb-2">
<li className="mb-2"><Link href="/concentres">Les concentrés</Link></li> <Link href="/produits/molecules">Lien 4</Link>
</ul> </li>
</div> <li className="mb-2">
<div className="col-6 col-lg-2 mb-3"> <Link href="/produits/concentres">Lien 5</Link>
<h5>Professionels</h5> </li>
<ul className="list-unstyled"> </ul>
<li className="mb-2"><Link href="/catalogue_ad_astra_2025.pdf" target="_blank" rel="noopener">Catalogue B2B</Link> </li> </div>
<li className="mb-2"><Link href="/pro/lien2" target="_blank" rel="noopener">Lien 2</Link> </li> <div className="col-6 col-lg-2 mb-3">
<li className="mb-2"><Link href="/pro/lien3" target="_blank" rel="noopener">Lien 3</Link></li> <h5>Documentation</h5>
<li className="mb-2"><Link href="/pro/lien4" target="_blank" rel="noopener">Lien 4</Link></li> <ul className="list-unstyled">
<li className="mb-2"> <Link href="/pro/lien5" target="_blank" rel="noopener">Lien 5</Link> </li> <li className="mb-2">
</ul> <Link href="/fleurs">Les fleurs</Link>
</div> </li>
<div className="col-6 col-lg-2 mb-3"> <li className="mb-2">
<h5>Contact</h5> <Link href="/resines">Les hashes</Link>
<ul className="list-unstyled"> </li>
<li className="mb-2"><Link href="/contact" target="_blank" rel="noopener">Lien 1</Link> </li> <li className="mb-2">
<li className="mb-2"><Link href="/mentions-legales" target="_blank" rel="noopener">Lien 2</Link> </li> <Link href="/molecules">Les molécules</Link>
<li className="mb-2"><Link href="/produits" target="_blank" rel="noopener">Lien 3</Link> </li> </li>
<li className="mb-2"><Link href="/produits" target="_blank" rel="noopener">Lien 4</Link></li> <li className="mb-2">
<li className="mb-2"><Link href="/produits" target="_blank" rel="noopener">Lien 5</Link> </li> <Link href="/concentres">Les concentrés</Link>
</ul> </li>
</div> </ul>
</div> </div>
</div> <div className="col-6 col-lg-2 mb-3">
<hr className="mt-3 mb-4" /> <h5>Professionels</h5>
<p className="text-muted px-4 small">Copyright © 2025 Ad Astra</p> <ul className="list-unstyled">
</footer> <li className="mb-2">
<Link href="/catalogue_ad_astra_2025.pdf" target="_blank" rel="noopener">
Catalogue B2B
</Link>{" "}
</li>
<li className="mb-2">
<Link href="/pro/lien2" target="_blank" rel="noopener">
Lien 2
</Link>{" "}
</li>
<li className="mb-2">
<Link href="/pro/lien3" target="_blank" rel="noopener">
Lien 3
</Link>
</li>
<li className="mb-2">
<Link href="/pro/lien4" target="_blank" rel="noopener">
Lien 4
</Link>
</li>
<li className="mb-2">
{" "}
<Link href="/pro/lien5" target="_blank" rel="noopener">
Lien 5
</Link>{" "}
</li>
</ul>
</div>
<div className="col-6 col-lg-2 mb-3">
<h5>Contact</h5>
<ul className="list-unstyled">
<li className="mb-2">
<Link href="/contact" target="_blank" rel="noopener">
Lien 1
</Link>{" "}
</li>
<li className="mb-2">
<Link href="/mentions-legales" target="_blank" rel="noopener">
Lien 2
</Link>{" "}
</li>
<li className="mb-2">
<Link href="/produits" target="_blank" rel="noopener">
Lien 3
</Link>{" "}
</li>
<li className="mb-2">
<Link href="/produits" target="_blank" rel="noopener">
Lien 4
</Link>
</li>
<li className="mb-2">
<Link href="/produits" target="_blank" rel="noopener">
Lien 5
</Link>{" "}
</li>
</ul>
</div>
</div>
</div>
<hr className="mt-3 mb-4" />
<p className="text-muted px-4 small">Copyright © 2025 Ad Astra</p>
</footer>
); );
@@ -1,5 +1,6 @@
import { ArticlePreview } from "@/utils/types/models"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import { ArticlePreview } from "@/utils/types/models";
import { Tag } from "../tag"; import { Tag } from "../tag";
import { FavoriteButton } from "../favoriteButton"; import { FavoriteButton } from "../favoriteButton";
@@ -13,7 +14,7 @@ export const ArticleCard = ({ article }: Props) => {
return ( return (
<div className="article-preview"> <div className="article-preview">
<div className="article-meta"> <div className="article-meta">
<Link href={`/profile/${author.username}`}>{author.image && <img src={author.image} alt="" />}</Link> <Link href={`/profile/${author.username}`}>{author.image && <Image src={author.image} alt="" />}</Link>
<div className="info"> <div className="info">
<Link href={`/profile/${author.username}`} className="author"> <Link href={`/profile/${author.username}`} className="author">
{author.username} {author.username}