diff --git a/src/front/Assets/logo_small_blue.svg b/src/front/Assets/logo_small_blue.svg index a52c0ab4..d3ac57f9 100644 --- a/src/front/Assets/logo_small_blue.svg +++ b/src/front/Assets/logo_small_blue.svg @@ -1,4 +1,4 @@ - - + + diff --git a/src/front/Assets/logo_standard_blue.svg b/src/front/Assets/logo_standard_blue.svg index 2095bba7..a4af4bde 100644 --- a/src/front/Assets/logo_standard_blue.svg +++ b/src/front/Assets/logo_standard_blue.svg @@ -1,15 +1,15 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/src/front/Components/DesignSystem/Table/MuiTable/classes.module.scss b/src/front/Components/DesignSystem/Table/MuiTable/classes.module.scss index a97f961c..1348e460 100644 --- a/src/front/Components/DesignSystem/Table/MuiTable/classes.module.scss +++ b/src/front/Components/DesignSystem/Table/MuiTable/classes.module.scss @@ -27,10 +27,6 @@ max-width: 270px; width: 100%; word-break: break-word; - - > :first-child { - width: 80%; - } } } diff --git a/src/front/Components/DesignSystem/Tag/classes.module.scss b/src/front/Components/DesignSystem/Tag/classes.module.scss index 9c206676..651f6877 100644 --- a/src/front/Components/DesignSystem/Tag/classes.module.scss +++ b/src/front/Components/DesignSystem/Tag/classes.module.scss @@ -1,6 +1,7 @@ @import "@Themes/constants.scss"; .root { + width: fit-content; padding: 2px 8px; border-radius: 360px; diff --git a/src/front/Components/DesignSystem/Tag/index.tsx b/src/front/Components/DesignSystem/Tag/index.tsx index 7df7faa4..090a90fd 100644 --- a/src/front/Components/DesignSystem/Tag/index.tsx +++ b/src/front/Components/DesignSystem/Tag/index.tsx @@ -19,7 +19,7 @@ export enum ETagVariant { type IProps = { label: string; color: ETagColor; - variant: ETagVariant; + variant?: ETagVariant; className?: string; }; @@ -36,7 +36,7 @@ const typoMap: Record = { }; export default function Tag(props: IProps) { - const { className, label, color, variant } = props; + const { className, label, color, variant = ETagVariant.REGULAR } = props; return (
diff --git a/src/front/Components/DesignSystem/Typography/index.tsx b/src/front/Components/DesignSystem/Typography/index.tsx index 04349b33..b306d822 100644 --- a/src/front/Components/DesignSystem/Typography/index.tsx +++ b/src/front/Components/DesignSystem/Typography/index.tsx @@ -8,6 +8,8 @@ type IProps = { color?: ETypoColor; className?: string; title?: string; + type?: "div" | "span"; + onClick?: () => void; }; export enum ETypo { @@ -142,12 +144,20 @@ export enum ETypoColor { } export default function Typography(props: IProps) { - const { typo, color, className, title, children } = props; + const { typo, color, className, title, children, type = "div", onClick } = props; const style = color ? ({ "--data-color": `var(${color})` } as React.CSSProperties) : undefined; + if (type === "span") { + return ( + + {children} + + ); + } + return ( -
+
{children}
); diff --git a/src/front/Components/Elements/Tabs/HorizontalTab/classes.module.scss b/src/front/Components/Elements/Tabs/HorizontalTab/classes.module.scss new file mode 100644 index 00000000..34782dad --- /dev/null +++ b/src/front/Components/Elements/Tabs/HorizontalTab/classes.module.scss @@ -0,0 +1,16 @@ +.root { + padding: 8px 16px; + font-size: 16px; + letter-spacing: 0.08px; + + border-bottom: 1px solid var(--color-neutral-500); + cursor: pointer; + + &[data-is-selected="true"] { + border-bottom: 2px solid var(--color-neutral-950, #24282e); + } + + &:hover { + border-bottom: 2px solid var(--color-neutral-950, #24282e); + } +} diff --git a/src/front/Components/Elements/Tabs/HorizontalTab/index.tsx b/src/front/Components/Elements/Tabs/HorizontalTab/index.tsx new file mode 100644 index 00000000..198cd857 --- /dev/null +++ b/src/front/Components/Elements/Tabs/HorizontalTab/index.tsx @@ -0,0 +1,34 @@ +import { useCallback } from "react"; +import classes from "./classes.module.scss"; +import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; +import useHoverable from "@Front/Hooks/useHoverable"; +import { ITabValue } from ".."; +export type ITab = { + label: React.ReactNode; +}; + +export type IProps = { + onSelect: (value: ITabValue) => void; + value: ITabValue; + isSelected: boolean; +} & ITab; + +export default function HorizontalTabs(props: IProps) { + const onClick = useCallback(() => props.onSelect(props.value), [props]); + + const { isHovered, handleMouseEnter, handleMouseLeave } = useHoverable(); + return ( +
+ + {props.label} + +
+ ); +} diff --git a/src/front/Components/Elements/Tabs/VerticalTabs/classes.module.scss b/src/front/Components/Elements/Tabs/VerticalTabs/classes.module.scss new file mode 100644 index 00000000..e7dfd493 --- /dev/null +++ b/src/front/Components/Elements/Tabs/VerticalTabs/classes.module.scss @@ -0,0 +1,6 @@ +.root { + padding: 8px 16px; + font-size: 16px; + letter-spacing: 0.08px; + cursor: pointer; +} diff --git a/src/front/Components/Elements/Tabs/VerticalTabs/index.tsx b/src/front/Components/Elements/Tabs/VerticalTabs/index.tsx new file mode 100644 index 00000000..e54247bb --- /dev/null +++ b/src/front/Components/Elements/Tabs/VerticalTabs/index.tsx @@ -0,0 +1,24 @@ +import { useCallback } from "react"; +import classes from "./classes.module.scss"; +import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; +import { ITabValue } from ".."; +export type ITab = { + label: React.ReactNode; +}; + +export type IProps = { + onSelect: (value: ITabValue) => void; + value: ITabValue; + isSelected: boolean; +} & ITab; + +export default function VerticalTabs(props: IProps) { + const onClick = useCallback(() => props.onSelect(props.value), [props]); + return ( +
+ + {props.label} + +
+ ); +} diff --git a/src/front/Components/Elements/Tabs/classes.module.scss b/src/front/Components/Elements/Tabs/classes.module.scss new file mode 100644 index 00000000..89a0e389 --- /dev/null +++ b/src/front/Components/Elements/Tabs/classes.module.scss @@ -0,0 +1,49 @@ +.root { + .hidden-tester { + display: flex; + overflow: hidden; + background: red; + height: 0px; + } + .horizontal-container { + display: flex; + flex-direction: row; + flex: 1; + .horizontal-tab { + display: flex; + justify-content: space-evenly; + overflow: hidden; + } + } + + .show-more-container { + position: relative; + border-bottom: 1px solid var(--color-neutral-500); + .show-more { + padding: 8px 16px; + display: flex; + color: white; + font-size: 16px; + justify-content: center; + align-items: center; + color: white; + cursor: pointer; + } + + .vertical-container { + position: absolute; + display: flex; + flex-direction: column; + top: 50px; + padding: var(--spacing-05, 4px) var(--spacing-2, 16px); + background: var(--color-generic-white, #fff); + + border: 1px solid var(--menu-border, #d7dce0); + border-radius: var(--menu-radius, 0px); + box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.1); + &[data-visible="false"] { + display: none; + } + } + } +} diff --git a/src/front/Components/Elements/Tabs/index.tsx b/src/front/Components/Elements/Tabs/index.tsx new file mode 100644 index 00000000..bd5d04bd --- /dev/null +++ b/src/front/Components/Elements/Tabs/index.tsx @@ -0,0 +1,119 @@ +import { useCallback, useEffect, useRef, useState } from "react"; +import classes from "./classes.module.scss"; +import HorizontalTab, { ITab } from "./HorizontalTab"; +import VerticalTabs from "./VerticalTabs"; +import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; +import { useDebounce, useWindowSize } from "@uidotdev/usehooks"; +import useOpenable from "@Front/Hooks/useOpenable"; + +export type ITabValue = T & { + id: unknown; +}; + +type ITabInternal = ITab & { + key?: string; + value: ITabValue; +}; + +type IProps = { + tabs: ITabInternal[]; + onSelect: (value: T) => void; +}; + +export default function Tabs(props: IProps) { + const { onSelect } = props; + const rootRef = useRef(null); + const [visibleElements, setVisibleElements] = useState[]>([]); + const [overflowedElements, setOverflowedElements] = useState[]>([]); + + const [selectedTab, setSelectedTab] = useState>(props.tabs[0]!.value); + + const { close, isOpen, toggle } = useOpenable(); + + const windowSize = useWindowSize(); + const windowSizeDebounced = useDebounce(windowSize, 100); + + const calculateVisibleElements = useCallback(() => { + const container = rootRef.current; + if (!container) return; + + const containerWidth = container.offsetWidth; + let totalWidth = 115; + let visibleCount = 0; + + const children = Array.from(container.children) as HTMLDivElement[]; + for (let i = 0; i < children.length; i++) { + totalWidth += children[i]!.offsetWidth; + if (totalWidth > containerWidth) { + break; + } + visibleCount++; + } + + setVisibleElements(props.tabs.slice(0, visibleCount)); + setOverflowedElements(props.tabs.slice(visibleCount)); + }, [props.tabs]); + + useEffect(() => { + calculateVisibleElements(); + }, [calculateVisibleElements, windowSizeDebounced]); + + const handleSelect = useCallback( + (value: ITabValue) => { + setSelectedTab(value); + onSelect(value); + close(); + }, + [close, onSelect], + ); + + return ( +
+
+ {props.tabs.map((element, index) => ( + + label={element.label} + key={element.key ?? index} + value={element.value} + onSelect={handleSelect} + isSelected={element.value.id === selectedTab.id} + /> + ))} +
+
+
+ {visibleElements.map((element, index) => ( + + label={element.label} + key={element.key ?? index} + value={element.value} + onSelect={handleSelect} + isSelected={element.value.id === selectedTab.id} + /> + ))} +
+ {overflowedElements.length > 0 && ( +
+
+ + {overflowedElements.length} de plus... + +
+
+ {overflowedElements.length > 0 && + overflowedElements.map((element, index) => ( + + label={element.label} + key={element.key ?? index} + value={element.value} + onSelect={handleSelect} + isSelected={selectedTab === element.value} + /> + ))} +
+
+ )} +
+
+ ); +} diff --git a/src/front/Components/Layouts/DesignSystem/index.tsx b/src/front/Components/Layouts/DesignSystem/index.tsx index c8d45fe9..37d26764 100644 --- a/src/front/Components/Layouts/DesignSystem/index.tsx +++ b/src/front/Components/Layouts/DesignSystem/index.tsx @@ -7,13 +7,58 @@ import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate"; import classes from "./classes.module.scss"; +import Tabs from "@Front/Components/Elements/Tabs"; +import { useCallback, useState } from "react"; export default function DesignSystem() { + const userDb = [ + { + username: "Maxime", + id: 1, + }, + { + username: "Vincent", + id: 2, + }, + { + username: "Massi", + id: 3, + }, + { + username: "Maxime", + id: 4, + }, + { + username: "Arnaud", + id: 5, + }, + ]; + + const [selectedTab, setSelectedTab] = useState<(typeof userDb)[number]>(userDb[0]!); + + const onSelect = useCallback((value: (typeof userDb)[number]) => { + setSelectedTab(value); + }, []); + return ( + DesignSystem + Tabs + + tabs={userDb.map((user) => ({ + label: user.username, + key: user.id.toString(), + value: user, + }))} + onSelect={onSelect} + /> +
+ + {selectedTab.id} - {selectedTab.username} + +
- DesignSystem
Circle Progress
@@ -83,48 +128,48 @@ export default function DesignSystem() { Buttons
- +
- +
- +
- +
- +
diff --git a/src/front/Components/Layouts/Folder/classes.module.scss b/src/front/Components/Layouts/Folder/classes.module.scss index 95a759ea..850483a8 100644 --- a/src/front/Components/Layouts/Folder/classes.module.scss +++ b/src/front/Components/Layouts/Folder/classes.module.scss @@ -1,5 +1,55 @@ @import "@Themes/constants.scss"; .root { -} + .content { + display: flex; + width: 648px; + flex-direction: column; + justify-content: center; + gap: var(--spacing-2xl, 40px); + .title-container { + display: flex; + flex-direction: column; + gap: var(--spacing-md, 16px); + align-self: stretch; + + .logo{ + fill: "red" + } + } + + .no-folder { + display: flex; + padding: var(--spacing-xl, 32px) var(--spacing-lg, 24px); + flex-direction: column; + gap: var(--spacing-lg, 24px); + align-self: stretch; + + border-radius: var(--radius-rounded, 16px); + background: var(--background-primary, #fff); + box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.1); + + svg { + stroke: var(--primary-default-base); + } + } + + .help-container { + display: flex; + gap: var(--spacing-lg, 24px); + + .box { + display: flex; + flex-direction: column; + gap: var(--spacing-sm, 8px); + } + + .separator { + background-color: var(--separator-stroke-light); + width: 1px; + align-self: stretch; + } + } + } +} diff --git a/src/front/Components/Layouts/Folder/index.tsx b/src/front/Components/Layouts/Folder/index.tsx index 4a9ddf07..1e01b43b 100644 --- a/src/front/Components/Layouts/Folder/index.tsx +++ b/src/front/Components/Layouts/Folder/index.tsx @@ -1,20 +1,77 @@ +import LogoIcon from "@Assets/logo_small_blue.svg"; +import Button, { EButtonVariant, EButtonStyleType } from "@Front/Components/DesignSystem/Button"; +import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; import DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard"; +import { DocumentIcon } from "@heroicons/react/24/outline"; import { OfficeFolder } from "le-coffre-resources/dist/Notary"; import { useCallback, useState } from "react"; +import Image from "next/image"; import classes from "./classes.module.scss"; +import Link from "next/link"; +import Module from "@Front/Config/Module"; export default function Folder() { - const [_selectedFolder, setSelectedFolder] = useState(null); + const [_folder, setFolder] = useState(null); const [_isArchivedModalOpen, _setIsArchivedModalOpen] = useState(true); const onSelectedFolder = useCallback((folder: OfficeFolder): void => { - setSelectedFolder(folder); + setFolder(folder); }, []); return ( -
+
+
+
+ logo + + + Bonjour John, bienvenue sur LeCoffre.io + + + Commencez par créer votre{" "} + + premier dossier + {" "} + pour profiter de toutes les fonctionnalités de notre plateforme sécurisée. + +
+ +
+ +
+ Aucun dossier créé + + Vous n'avez pas encore de dossier créé. En quelques clics, commencez un nouveau dossier pour organiser et + sécuriser vos documents notariés. + +
+ + + +
+ +
+
+ Besoin d'aide ? + Consultez nos guides pour bien démarrer. + +
+
+ +
+ Vous avez des questions ? + Notre équipe de support est là pour vous aider. + +
+
+
+
); } diff --git a/src/front/Components/Layouts/Subscription/Components/SubscriptionClientInfos/index.tsx b/src/front/Components/Layouts/Subscription/Components/SubscriptionClientInfos/index.tsx index 74959d00..a030e002 100644 --- a/src/front/Components/Layouts/Subscription/Components/SubscriptionClientInfos/index.tsx +++ b/src/front/Components/Layouts/Subscription/Components/SubscriptionClientInfos/index.tsx @@ -16,7 +16,7 @@ export default function SubscriptionClientInfos(props: IProps) { {customer.email} - {/* + {/* Adresse de facturation */}