diff --git a/.env.development b/.env.development
new file mode 100644
index 0000000..8b1a401
--- /dev/null
+++ b/.env.development
@@ -0,0 +1,2 @@
+APP_ENV="development"
+API_BASE_URL=http://localhost:3200
diff --git a/.env.production b/.env.production
new file mode 100644
index 0000000..a122a52
--- /dev/null
+++ b/.env.production
@@ -0,0 +1,2 @@
+APP_ENV="production"
+API_BASE_URL=http://api.adastra-cbd.com/api
diff --git a/.env.sample b/.env.sample
index 596913e..7451781 100644
--- a/.env.sample
+++ b/.env.sample
@@ -1 +1,2 @@
-API_BASE_URL=http://localhost/api
+APP_ENV="development"
+API_BASE_URL=http://localhost:3200/api
diff --git a/.husky/pre-commit b/.husky/pre-commit
index 458b644..6be6160 100644
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,3 +1,3 @@
npm test
-prettier $(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g') --write --ignore-unknown
-git update-index --again
\ No newline at end of file
+#prettier $(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g') --write --ignore-unknown
+#git update-index --again
\ No newline at end of file
diff --git a/src/app/_components/timeClock/timeClock.tsx b/src/app/_components/timeClock/timeClock.tsx
index 9db3209..c2ca8bd 100644
--- a/src/app/_components/timeClock/timeClock.tsx
+++ b/src/app/_components/timeClock/timeClock.tsx
@@ -3,182 +3,182 @@
import React, { useEffect } from "react";
const TimeClock: React.FC = () => {
- 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
- ];
+ 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 blocks: Array = [];
- const digits = Array.from(document.querySelectorAll(".block"));
+ const blocks: Array = [];
+ const digits = Array.from(document.querySelectorAll(".block"));
- for (let i = 0; i < 4; i++) {
- blocks.push(digits.slice(i * 15, i * 15 + 15));
- }
-
- const setNum = (block: Array, num: number) => {
- 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;
- }
+ for (let i = 0; i < 4; i++) {
+ blocks.push(digits.slice(i * 15, i * 15 + 15));
}
- }
- if (m !== time.m) {
- setNum(blocks[2], parseInt(Array.from(m)[0]));
- setNum(blocks[3], parseInt(Array.from(m)[1]));
- time.m = m;
- }
+ const setNum = (block: Array, num: number) => {
+ const n = numbers[num];
+ for (let i = 0; i < block.length; i++) {
+ block[i].classList[n[i] === 1 ? "add" : "remove"]("active");
+ }
+ };
- if (h !== time.h) {
- setNum(blocks[0], parseInt(Array.from(h)[0]));
- setNum(blocks[1], parseInt(Array.from(h)[1]));
- time.h = h;
- }
- window.requestAnimationFrame(animator);
- };
+ const time = {
+ s: "",
+ m: "",
+ h: "",
+ p: 0,
+ };
- // init
- window.requestAnimationFrame(animator);
+ // time loop
+ const animator = () => {
+ const d = new Date();
+ let h = d.getHours().toString(),
+ m = d.getMinutes().toString(),
+ s = d.getSeconds().toString();
- // toggle button
- const d = new Date();
- 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;
- }, []);
+ s = s.length === 1 ? "0" + s : s;
+ m = m.length === 1 ? "0" + m : m;
+ h = h.length === 1 ? "0" + h : h;
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
+ 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;
+ }
+ }
+ }
+
+ if (m !== time.m) {
+ setNum(blocks[2], parseInt(Array.from(m)[0]));
+ setNum(blocks[3], parseInt(Array.from(m)[1]));
+ time.m = m;
+ }
+
+ if (h !== time.h) {
+ setNum(blocks[0], parseInt(Array.from(h)[0]));
+ setNum(blocks[1], parseInt(Array.from(h)[1]));
+ time.h = h;
+ }
+ window.requestAnimationFrame(animator);
+ };
+
+ // init
+ window.requestAnimationFrame(animator);
+
+ // toggle button
+ const d = new Date();
+ 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;
+ }, []);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
};
export default TimeClock;
diff --git a/src/app/article/[slug]/_components/articleArea/articleArea.tsx b/src/app/article/[slug]/_components/articleArea/articleArea.tsx
index bcefd94..4c07695 100644
--- a/src/app/article/[slug]/_components/articleArea/articleArea.tsx
+++ b/src/app/article/[slug]/_components/articleArea/articleArea.tsx
@@ -1,3 +1,4 @@
+import { Container, Col, Row } from "react-bootstrap";
import { Button } from "@/modules/common/components/button";
import { DeleteArticleButton } from "@/modules/features/article/components/deleteArticleButton";
import { FavoriteButton } from "@/modules/features/article/components/favoriteButton";
@@ -15,66 +16,65 @@ import { getSession } from "@/utils/auth/session";
import { fetchCurrentUser } from "@/modules/features/auth/fetch/fetchCurrentUser";
const Actions = ({ article, currentUser }: { article: Article; currentUser?: User }) => {
- const profile = article.author;
+ const profile = article.author;
- return (
-
-
{profile.image &&
}
-
-
- {profile.username}
-
- {article.createdAt.toDateString()}
-
- {showFollowButton(profile.username, currentUser) && (
-
- )}
-
- {showEditArticleButton(profile.username, currentUser) && (
-
- )}
- {showDeleteArticleButton(profile.username, currentUser) && (
-
- )}
-
- );
+ return (
+
+
{profile.image &&
}
+
+
+ {profile.username}
+
+ {article.createdAt.toDateString()}
+
+ {showFollowButton(profile.username, currentUser) && (
+
+ )}
+
+ {showEditArticleButton(profile.username, currentUser) && (
+
+ )}
+ {showDeleteArticleButton(profile.username, currentUser) && (
+
+ )}
+
+ );
};
export const ArticleArea = async ({ slug, children }: { slug: string; children: ReactNode }) => {
- const article = await fetchArticle(slug);
- const body = await convertMarkdownToHtml(article.body);
- const currentUser = (await getSession()) ? await fetchCurrentUser() : undefined;
+ const article = await fetchArticle(slug);
+ const body = await convertMarkdownToHtml(article.body);
+ const currentUser = (await getSession()) ? await fetchCurrentUser() : undefined;
- return (
-
-
-
-
-
-
-
-
- {article.tagList.map((tag, index) => (
-
- {tag}
-
- ))}
-
-
-
-
-
- {children}
-
-
- );
+ return (
+
+
+ {article.title}
+
+
+
+
+
+
+
+ {article.tagList.map((tag, index) => (
+ -
+
+ {tag}
+
+
+ ))}
+
+
+
+
+
+ {children}
+
+
+ );
};
diff --git a/src/app/article/[slug]/_components/commentCard/presentation.tsx b/src/app/article/[slug]/_components/commentCard/presentation.tsx
index eb361be..764e3f6 100644
--- a/src/app/article/[slug]/_components/commentCard/presentation.tsx
+++ b/src/app/article/[slug]/_components/commentCard/presentation.tsx
@@ -1,38 +1,39 @@
+import { Button, Form } from "react-bootstrap";
import Link from "next/link";
import Image from "next/image";
import { Comment } from "@/utils/types/models";
import styles from "./presentation.module.css";
type Props = {
- comment: Comment;
- showDeleteCommentButton?: boolean;
- deleteCommentAction?: () => void;
- isPending?: boolean;
+ comment: Comment;
+ showDeleteCommentButton?: boolean;
+ deleteCommentAction?: () => void;
+ isPending?: boolean;
};
export const CommentCard = ({ comment, showDeleteCommentButton, deleteCommentAction }: Props) => {
- return (
-
-
-
-
- {comment.author.image && }
-
-
-
- {comment.author.username}
-
- {comment.createdAt.toDateString()}
- {showDeleteCommentButton && (
-
- )}
-
-
- );
+ return (
+
+
+
+
+ {comment.author.image && }
+
+
+
+ {comment.author.username}
+
+ {comment.createdAt.toDateString()}
+ {showDeleteCommentButton && (
+
+ )}
+
+
+ );
};
diff --git a/src/app/article/[slug]/_components/commentForm/presentation.tsx b/src/app/article/[slug]/_components/commentForm/presentation.tsx
index 1118aa7..3a4b99e 100644
--- a/src/app/article/[slug]/_components/commentForm/presentation.tsx
+++ b/src/app/article/[slug]/_components/commentForm/presentation.tsx
@@ -1,5 +1,5 @@
+import { Button, Form } from "react-bootstrap";
import Image from "next/image";
-import { Button } from "@/modules/common/components/button";
import { ErrorMessage } from "@/modules/common/components/errorMessage";
import { SubmissionResult, useForm } from "@conform-to/react";
import { parseWithZod } from "@conform-to/zod";
@@ -7,57 +7,62 @@ import { startTransition } from "react";
import { inputsSchema } from "./types";
type Props = {
- slug?: string;
- authorImage?: string;
- result?: SubmissionResult;
- postCommentAction?: (formData: FormData) => void;
- isPending?: boolean;
+ slug?: string;
+ authorImage?: string;
+ result?: SubmissionResult;
+ postCommentAction?: (formData: FormData) => void;
+ isPending?: boolean;
};
export const CommentForm = ({ slug, authorImage, result, postCommentAction, isPending }: Props) => {
- const [form, fields] = useForm({
- defaultValue: {
- slug,
- },
- lastResult: result,
- onValidate({ formData }) {
- return parseWithZod(formData, { schema: inputsSchema });
- },
- // onSubmit is defined to avoid resetting form after successful submission
- // see https://github.com/edmundhung/conform/discussions/606
- onSubmit(event, { formData }) {
- event.preventDefault();
- startTransition(() => {
- postCommentAction?.(formData);
- });
- },
- shouldRevalidate: "onBlur",
- });
+ const [form, fields] = useForm({
+ defaultValue: {
+ slug,
+ },
+ lastResult: result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: inputsSchema });
+ },
+ // onSubmit is defined to avoid resetting form after successful submission
+ // see https://github.com/edmundhung/conform/discussions/606
+ onSubmit(event, { formData }) {
+ event.preventDefault();
+ startTransition(() => {
+ postCommentAction?.(formData);
+ });
+ },
+ shouldRevalidate: "onBlur",
+ });
- const errors = Object.values(form.allErrors).flat();
+ const errors = Object.values(form.allErrors).flat();
- return (
- <>
-
- >
- );
+ return (
+ <>
+
+
+
+
+
+
+ {authorImage && }
+
+
+
+ >
+ );
};
diff --git a/src/app/article/[slug]/page.tsx b/src/app/article/[slug]/page.tsx
index cbf57f3..311d170 100644
--- a/src/app/article/[slug]/page.tsx
+++ b/src/app/article/[slug]/page.tsx
@@ -1,30 +1,31 @@
+import { Col, Row } from "react-bootstrap";
+import { Suspense } from "react";
import { fetchCurrentUser } from "@/modules/features/auth/fetch/fetchCurrentUser";
import { getSession } from "@/utils/auth/session";
-import { Suspense } from "react";
import { ArticleArea } from "./_components/articleArea";
import { CommentForm } from "./_components/commentForm";
import { CommentList } from "./_components/commentList";
type Params = Promise<{
- slug: string;
+ slug: string;
}>;
const Page = async (props: { params: Params }) => {
- const currentUserPromise = (await getSession()) ? fetchCurrentUser() : undefined;
- const params = await props.params;
+ const currentUserPromise = (await getSession()) ? fetchCurrentUser() : undefined;
+ const params = await props.params;
- return (
-
-
-
-
- ⌛Loading comments...}>
-
-
-
-
-
- );
+ return (
+
+
+
+
+ ⌛Loading comments...
}>
+
+
+
+
+
+ );
};
export default Page;
diff --git a/src/app/articles/page.tsx b/src/app/articles/page.tsx
new file mode 100644
index 0000000..dcff1fe
--- /dev/null
+++ b/src/app/articles/page.tsx
@@ -0,0 +1,78 @@
+import { Container, Col, Row } from "react-bootstrap";
+import { getSession } from "@/utils/auth/session";
+import { ExhaustiveError } from "@/utils/errors";
+import clsx from "clsx";
+import Link from "next/link";
+import { Suspense } from "react";
+import { FeedArticleList } from "../_components/feedArticleList";
+import { GlobalArticleList } from "../_components/globalArticleList";
+import { TagArticleList } from "../_components/tagArticleList";
+import { TagList } from "../_components/tagList";
+import { SearchParams } from "../_types";
+//import { ArticlesList } from "./_components/articlesList";
+
+const ArticleList = (searchParams: SearchParams) => {
+ switch (searchParams.tab) {
+ case "yours":
+ return ;
+ case "global":
+ return ;
+ case "tag":
+ return ;
+ default:
+ throw new ExhaustiveError(searchParams.tab, "all tab cases are not covered");
+ }
+};
+
+const Page = async (props: { searchParams: Promise<{ [key: string]: string | string[] | undefined }> }) => {
+ const session = await getSession();
+ const searchParams = SearchParams.parse(await props.searchParams);
+
+ return (
+
+
+
+
+
+
+
+ {session && (
+ -
+
+ Your Feed
+
+
+ )}
+ -
+
+ Global Feed
+
+
+ {searchParams.tag && (
+ -
+
+ #{searchParams.tag}
+
+
+ )}
+
+
+ ⌛Chargement...}>
+
+
+
+
+ ⌛Chargement...}>
+
+
+
+
+
+
+ );
+};
+
+export default Page;
diff --git a/src/app/editor/[slug]/page.tsx b/src/app/editor/[slug]/page.tsx
index aa9f731..b8da965 100644
--- a/src/app/editor/[slug]/page.tsx
+++ b/src/app/editor/[slug]/page.tsx
@@ -1,29 +1,30 @@
+import { Container, Col, Row } from "react-bootstrap";
import { UpdateArticleEditor } from "@/modules/features/article/components/articleEditor";
import { fetchArticle } from "@/modules/features/article/fetch/fetchArticle";
import { Suspense } from "react";
type Props = {
- params: Promise<{
- slug: string;
- }>;
+ params: Promise<{
+ slug: string;
+ }>;
};
const Page = async ({ params }: Props) => {
- const article = fetchArticle((await params).slug);
+ const article = fetchArticle((await params).slug);
- return (
-
-
-
-
- ⌛Loading...}>
-
-
-
+ return (
+
+
+
+
+ ⌛ Chargement...}>
+
+
+
+
+
-
-
- );
+ );
};
export default Page;
diff --git a/src/app/editor/page.tsx b/src/app/editor/page.tsx
index 59303cb..f68f9d1 100644
--- a/src/app/editor/page.tsx
+++ b/src/app/editor/page.tsx
@@ -1,15 +1,16 @@
+import { Container, Col, Row } from "react-bootstrap";
import { CreateArticleEditor } from "@/modules/features/article/components/articleEditor";
const Page = () => (
-
+
);
export default Page;
diff --git a/src/app/error.tsx b/src/app/error.tsx
index e2688ee..e6375a6 100644
--- a/src/app/error.tsx
+++ b/src/app/error.tsx
@@ -1,25 +1,37 @@
"use client";
-import { Button } from "@/modules/common/components/button";
+//import { Button } from "@/modules/common/components/button";
+import { Container, Button, Col, Row } from "react-bootstrap";
+import TimeClock from "./_components/timeClock/timeClock";
const Error = ({
- reset,
+ reset,
}: {
- error: Error & {
- digest?: string;
- };
- reset: () => void;
+ error: Error & {
+ digest?: string;
+ };
+ reset: () => void;
}) => {
- return (
-
-
-
⚠️Something went wrong!
-
-
-
- );
+ return (
+
+
+
+
+ ⚠️ Une erreur est survenue!
+ La page que vous vouliez consulter n'est pas d'isponible pour le moment.
+
+
+
+
+
+
+
+
+
+
+ );
};
export default Error;
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index ab35f01..2bd51b9 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -58,11 +58,11 @@ const RootLayout = ({
}>) => {
return (
-
+
-
- {children}
-
+
+ {children}
+
diff --git a/src/app/login/_components/loginForm/presentation.tsx b/src/app/login/_components/loginForm/presentation.tsx
index 82c04f9..0d76b8d 100644
--- a/src/app/login/_components/loginForm/presentation.tsx
+++ b/src/app/login/_components/loginForm/presentation.tsx
@@ -6,62 +6,62 @@ import { startTransition } from "react";
import { inputsSchema } from "./types";
type Props = {
- action?: (formData: FormData) => void;
- isPending?: boolean;
- result?: SubmissionResult
;
+ action?: (formData: FormData) => void;
+ isPending?: boolean;
+ result?: SubmissionResult;
};
export const LoginForm = ({ result, action, isPending }: Props) => {
- const [form, fields] = useForm({
- lastResult: result,
- onValidate({ formData }) {
- return parseWithZod(formData, { schema: inputsSchema });
- },
- // onSubmit is defined to avoid resetting form after successful submission
- // see https://github.com/edmundhung/conform/discussions/606
- onSubmit(event, { formData }) {
- event.preventDefault();
- startTransition(() => {
- action?.(formData);
- });
- },
- shouldValidate: "onBlur",
- shouldRevalidate: "onBlur",
- });
+ const [form, fields] = useForm({
+ lastResult: result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: inputsSchema });
+ },
+ // onSubmit is defined to avoid resetting form after successful submission
+ // see https://github.com/edmundhung/conform/discussions/606
+ onSubmit(event, { formData }) {
+ event.preventDefault();
+ startTransition(() => {
+ action?.(formData);
+ });
+ },
+ shouldValidate: "onBlur",
+ shouldRevalidate: "onBlur",
+ });
- return (
- <>
-
-
- Adresse email
-
-
-
-
- Mot de passe
-
-
-
-
-
-
-
- >
- );
+ return (
+ <>
+
+
+ Adresse email
+
+
+
+
+ Mot de passe
+
+
+
+
+
+
+
+ >
+ );
};
diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx
index be87296..fc584ee 100644
--- a/src/app/login/page.tsx
+++ b/src/app/login/page.tsx
@@ -1,19 +1,20 @@
+import { Container, Col, Row } from "react-bootstrap";
import Link from "next/link";
import { LoginForm } from "./_components/loginForm";
const Page = () => (
-
-
-
-
-
Se connecter
-
- Pas encore de compte?
-
-
-
-
-
-
+
+
+
+
+ Se connecter
+
+ Pas encore de compte?
+
+
+
+
+
+
);
export default Page;
diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx
index e00a31c..194acd5 100644
--- a/src/app/not-found.tsx
+++ b/src/app/not-found.tsx
@@ -1,11 +1,13 @@
+
+import { Container, Button } from "react-bootstrap";
const NotFound = () => {
- return (
-
-
-
This page could not be found.
-
-
- );
+ return (
+
+
+ ⚠️ Cette page n'existe pas.
+
+
+ );
};
export default NotFound;
diff --git a/src/app/page.tsx b/src/app/page.tsx
index d277b53..3b6f841 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,89 +1,23 @@
-import { getSession } from "@/utils/auth/session";
-import { ExhaustiveError } from "@/utils/errors";
-import clsx from "clsx";
-import Link from "next/link";
-import { Suspense } from "react";
import { Container, Col, Row } from "react-bootstrap";
-import { FeedArticleList } from "./_components/feedArticleList";
-import { GlobalArticleList } from "./_components/globalArticleList";
-import { TagArticleList } from "./_components/tagArticleList";
-import { TagList } from "./_components/tagList";
-import { SearchParams } from "./_types";
import TimeClock from "./_components/timeClock/timeClock";
-const ArticleList = (searchParams: SearchParams) => {
- switch (searchParams.tab) {
- case "yours":
- return ;
- case "global":
- return ;
- case "tag":
- return ;
- default:
- throw new ExhaustiveError(searchParams.tab, "all tab cases are not covered");
- }
-};
const Page = async (props: { searchParams: Promise<{ [key: string]: string | string[] | undefined }> }) => {
- const session = await getSession();
- const searchParams = SearchParams.parse(await props.searchParams);
-
- return (
-
-
-
-
- Ad Astra, bientôt en ligne!
- Encore un peu de patience, notre site sera disponible d'ici peu.
-
-
-
-
-
-
-
-
-
-
-
-
- {session && (
- -
-
- Your Feed
-
-
- )}
- -
-
- Global Feed
-
-
- {searchParams.tag && (
- -
-
- #{searchParams.tag}
-
-
- )}
-
-
- ⌛Chargement...}>
-
-
-
-
- ⌛Chargement...}>
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+ Ad Astra, bientôt en ligne!
+ Encore un peu de patience, notre site sera disponible d'ici peu.
+
+
+
+
+
+
+
+ );
};
export default Page;
diff --git a/src/app/profile/[username]/layout.tsx b/src/app/profile/[username]/layout.tsx
index 3655287..c4a337b 100644
--- a/src/app/profile/[username]/layout.tsx
+++ b/src/app/profile/[username]/layout.tsx
@@ -8,43 +8,43 @@ import { getSession } from "@/utils/auth/session";
import { showEditProfileSettingsButton, showFollowButton } from "./_functions";
type Props = {
- children: ReactNode;
- params: Promise<{
- username: string;
- }>;
+ children: ReactNode;
+ params: Promise<{
+ username: string;
+ }>;
};
const Layout = async ({ children, params }: Props) => {
- const profile = await fetchProfile((await params).username);
- const currentUser = (await getSession()) ? await fetchCurrentUser() : undefined;
+ const profile = await fetchProfile((await params).username);
+ const currentUser = (await getSession()) ? await fetchCurrentUser() : undefined;
- return (
-
-
-
-
-
- {profile.image &&
}
-
{profile.username}
- {profile.bio &&
{profile.bio}
}
- {showFollowButton(profile.username, currentUser) &&
}
- {showEditProfileSettingsButton(profile.username, currentUser) && (
-
- )}
+ return (
+
+
+
+
+
+ {profile.image &&
}
+
{profile.username}
+ {profile.bio &&
{profile.bio}
}
+ {showFollowButton(profile.username, currentUser) &&
}
+ {showEditProfileSettingsButton(profile.username, currentUser) && (
+
+ )}
+
+
+
-
-
-
-
-
- );
+ );
};
export default Layout;
diff --git a/src/app/profile/[username]/page.tsx b/src/app/profile/[username]/page.tsx
index 9b88877..a6fc57e 100644
--- a/src/app/profile/[username]/page.tsx
+++ b/src/app/profile/[username]/page.tsx
@@ -5,35 +5,35 @@ import { MyArticleList } from "./_components/myArticleList";
import { searchParamsSchema } from "./_types";
const ProfilePage = async (props: {
- params: Promise<{
- username: string;
- }>;
- searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
+ params: Promise<{
+ username: string;
+ }>;
+ searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
}) => {
- const pathParams = decodePathParams(await props.params);
- const searchParams = searchParamsSchema.parse(await props.searchParams);
+ const pathParams = decodePathParams(await props.params);
+ const searchParams = searchParamsSchema.parse(await props.searchParams);
- return (
- <>
-
-
- -
-
- My Articles
-
-
- -
-
- Favorited Articles
-
-
-
-
-
⌛Loading...}>
-
-
- >
- );
+ return (
+ <>
+
+
+ -
+
+ My Articles
+
+
+ -
+
+ Favorited Articles
+
+
+
+
+
⌛Loading...}>
+
+
+ >
+ );
};
export default ProfilePage;
diff --git a/src/app/register/_components/registrationForm/presentation.tsx b/src/app/register/_components/registrationForm/presentation.tsx
index 0dfde8a..57792f3 100644
--- a/src/app/register/_components/registrationForm/presentation.tsx
+++ b/src/app/register/_components/registrationForm/presentation.tsx
@@ -7,95 +7,95 @@ import { startTransition } from "react";
import { inputsSchema } from "./types";
type Props = {
- action?: (formData: FormData) => void;
- isPending?: boolean;
- result?: SubmissionResult
;
+ action?: (formData: FormData) => void;
+ isPending?: boolean;
+ result?: SubmissionResult;
};
export const RegistrationForm = ({ result, action, isPending }: Props) => {
- const [form, fields] = useForm({
- lastResult: result,
- onValidate({ formData }) {
- return parseWithZod(formData, { schema: inputsSchema });
- },
- // onSubmit is defined to avoid resetting form after successful submission
- // see https://github.com/edmundhung/conform/discussions/606
- onSubmit(event, { formData }) {
- event.preventDefault();
- startTransition(() => {
- action?.(formData);
- });
- },
- shouldValidate: "onBlur",
- shouldRevalidate: "onBlur",
- });
+ const [form, fields] = useForm({
+ lastResult: result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: inputsSchema });
+ },
+ // onSubmit is defined to avoid resetting form after successful submission
+ // see https://github.com/edmundhung/conform/discussions/606
+ onSubmit(event, { formData }) {
+ event.preventDefault();
+ startTransition(() => {
+ action?.(formData);
+ });
+ },
+ shouldValidate: "onBlur",
+ shouldRevalidate: "onBlur",
+ });
- return (
- <>
-
-
- Nom
-
-
-
-
- Prénom
-
-
-
-
- Pseudo
-
-
-
-
- Adresse email
-
-
-
-
- Mot de passe
-
-
-
-
-
-
-
- >
- );
+ return (
+ <>
+
+
+ Prénom
+
+
+
+
+ Nom
+
+
+
+
+ Pseudo
+
+
+
+
+ Adresse email
+
+
+
+
+ Mot de passe
+
+
+
+
+
+
+
+ >
+ );
};
diff --git a/src/app/register/page.tsx b/src/app/register/page.tsx
index 78334b7..b94fc3e 100644
--- a/src/app/register/page.tsx
+++ b/src/app/register/page.tsx
@@ -1,20 +1,21 @@
+import { Container, Col, Row } from "react-bootstrap";
import Link from "next/link";
import { RegistrationForm } from "./_components/registrationForm";
const Page = () => (
-
-
-
-
-
Se connecter
-
- Déjà un compte?
-
-
-
-
-
-
+
+
+
+
+ Créer un compte
+
+ Déjà un compte?
+
+
+
+
+
+
);
export default Page;
diff --git a/src/app/settings/_components/presentation.tsx b/src/app/settings/_components/presentation.tsx
index e51d30c..a12276f 100644
--- a/src/app/settings/_components/presentation.tsx
+++ b/src/app/settings/_components/presentation.tsx
@@ -1,4 +1,4 @@
-import { Button } from "@/modules/common/components/button";
+import { Button, Form } from "react-bootstrap";
import { ErrorMessage } from "@/modules/common/components/errorMessage";
import { User } from "@/utils/types/models";
import { SubmissionResult, useForm } from "@conform-to/react";
@@ -7,105 +7,117 @@ import { startTransition } from "react";
import { inputsSchema } from "./types";
type Props = {
- user?: User;
- action?: (formData: FormData) => void;
- isPending?: boolean;
- result?: SubmissionResult;
+ user?: User;
+ action?: (formData: FormData) => void;
+ isPending?: boolean;
+ result?: SubmissionResult;
};
export const SettingsForm = ({ user, action, isPending, result }: Props) => {
- const [form, fields] = useForm({
- lastResult: result,
- onValidate({ formData }) {
- return parseWithZod(formData, { schema: inputsSchema });
- },
- // onSubmit is defined to avoid resetting form after successful submission
- // see https://github.com/edmundhung/conform/discussions/606
- onSubmit(event, { formData }) {
- event.preventDefault();
- startTransition(() => {
- action?.(formData);
- });
- },
- defaultValue: { ...user },
- shouldValidate: "onBlur",
- shouldRevalidate: "onBlur",
- });
+ const [form, fields] = useForm({
+ lastResult: result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: inputsSchema });
+ },
+ // onSubmit is defined to avoid resetting form after successful submission
+ // see https://github.com/edmundhung/conform/discussions/606
+ onSubmit(event, { formData }) {
+ event.preventDefault();
+ startTransition(() => {
+ action?.(formData);
+ });
+ },
+ defaultValue: { ...user },
+ shouldValidate: "onBlur",
+ shouldRevalidate: "onBlur",
+ });
- return (
- <>
-
-
- >
- );
+ return (
+ <>
+
+
+ Pseudo
+
+
+
+
+ Adresse email
+
+
+
+
+ Prénom
+
+
+
+
+ Nom
+
+
+
+
+ Mot de passe
+
+
+
+
+ Bio
+
+
+
+
+ Image
+
+
+
+
+
+
+
+ >
+ );
};
diff --git a/src/app/settings/_components/types.ts b/src/app/settings/_components/types.ts
index d683b98..741ae39 100644
--- a/src/app/settings/_components/types.ts
+++ b/src/app/settings/_components/types.ts
@@ -1,10 +1,12 @@
import { z } from "zod";
export const inputsSchema = z.object({
- image: z.string().max(200).optional(),
username: z.string().max(200),
- bio: z.string().max(200).optional(),
email: z.string().max(200).email(),
+ firstname: z.string().max(200),
+ lastname: z.string().max(200),
+ bio: z.string().max(200).optional(),
+ image: z.string().max(200).optional(),
password: z.string().min(4).max(200).optional(),
});
diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx
index 1408a7f..e4d7b6a 100644
--- a/src/app/settings/page.tsx
+++ b/src/app/settings/page.tsx
@@ -1,27 +1,28 @@
+import { Container, Col, Row } from "react-bootstrap";
import { LogoutButton } from "@/modules/features/auth/components/logoutButton";
import { fetchCurrentUser } from "@/modules/features/auth/fetch/fetchCurrentUser";
import { Suspense } from "react";
import { SettingsForm } from "./_components";
const Page = async () => {
- const user = fetchCurrentUser();
+ const user = fetchCurrentUser();
- return (
-
-
-
-
-
Your Settings
- ⌛Loading...}>
-
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+ Vos paramètres
+ ⌛ Chargement...}>
+
+
+
+
+
+
+
+
+ );
};
export default Page;
diff --git a/src/modules/common/components/button/buttonOffcanvas.tsx b/src/modules/common/components/button/buttonOffcanvas.tsx
index 9640c7b..db22702 100644
--- a/src/modules/common/components/button/buttonOffcanvas.tsx
+++ b/src/modules/common/components/button/buttonOffcanvas.tsx
@@ -15,24 +15,19 @@ const ExampleOffcanvas: React.FC = ({ className }) => {
return (
<>
-