diff --git a/src/components/domains/dashboard/cards/PalmCard/PalmCard.tsx b/src/components/domains/dashboard/cards/PalmCard/PalmCard.tsx
index f216ccf..5cb649b 100644
--- a/src/components/domains/dashboard/cards/PalmCard/PalmCard.tsx
+++ b/src/components/domains/dashboard/cards/PalmCard/PalmCard.tsx
@@ -1,7 +1,6 @@
import Image from "next/image";
-import { Card, MetaLabel, Typography } from "@/components/ui";
-import { IconName } from "@/components/ui/Icon/Icon";
+import { Card, IconName, MetaLabel, Typography } from "@/components/ui";
import { Action } from "@/entities/dashboard/types";
import styles from "./PalmCard.module.scss";
diff --git a/src/components/domains/dashboard/sections/AdvisersSection/AdvisersSection.module.scss b/src/components/domains/dashboard/sections/AdvisersSection/AdvisersSection.module.scss
index 6858c69..bcd02ce 100644
--- a/src/components/domains/dashboard/sections/AdvisersSection/AdvisersSection.module.scss
+++ b/src/components/domains/dashboard/sections/AdvisersSection/AdvisersSection.module.scss
@@ -9,6 +9,10 @@
.grid {
padding-right: 16px;
+
+ &.vertical {
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)) !important;
+ }
}
.skeleton.skeleton {
diff --git a/src/components/domains/dashboard/sections/AdvisersSection/AdvisersSection.tsx b/src/components/domains/dashboard/sections/AdvisersSection/AdvisersSection.tsx
index db2193d..75999e8 100644
--- a/src/components/domains/dashboard/sections/AdvisersSection/AdvisersSection.tsx
+++ b/src/components/domains/dashboard/sections/AdvisersSection/AdvisersSection.tsx
@@ -1,4 +1,5 @@
import { use } from "react";
+import clsx from "clsx";
import { Grid, Section, Skeleton } from "@/components/ui";
import { Assistant } from "@/entities/dashboard/types";
@@ -7,17 +8,24 @@ import { AdviserCard } from "../../cards";
import styles from "./AdvisersSection.module.scss";
+interface AdvisersSectionProps {
+ promise: Promise
;
+ gridDisplayMode?: "vertical" | "horizontal";
+}
+
export default function AdvisersSection({
promise,
-}: {
- promise: Promise;
-}) {
+ gridDisplayMode = "horizontal",
+}: AdvisersSectionProps) {
const assistants = use(promise);
const columns = Math.ceil(assistants?.length / 2);
return (
-
+
{assistants.map(adviser => (
))}
diff --git a/src/components/domains/dashboard/sections/CompatibilitySection/CompatibilitySection.module.scss b/src/components/domains/dashboard/sections/CompatibilitySection/CompatibilitySection.module.scss
index 2dd837e..ec22f16 100644
--- a/src/components/domains/dashboard/sections/CompatibilitySection/CompatibilitySection.module.scss
+++ b/src/components/domains/dashboard/sections/CompatibilitySection/CompatibilitySection.module.scss
@@ -9,6 +9,10 @@
.grid {
padding-right: 16px;
+
+ &.vertical {
+ grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)) !important;
+ }
}
.skeleton.skeleton {
diff --git a/src/components/domains/dashboard/sections/CompatibilitySection/CompatibilitySection.tsx b/src/components/domains/dashboard/sections/CompatibilitySection/CompatibilitySection.tsx
index cf98a10..b0455c8 100644
--- a/src/components/domains/dashboard/sections/CompatibilitySection/CompatibilitySection.tsx
+++ b/src/components/domains/dashboard/sections/CompatibilitySection/CompatibilitySection.tsx
@@ -2,6 +2,7 @@
import { use } from "react";
import Link from "next/link";
+import clsx from "clsx";
import { Grid, Section, Skeleton } from "@/components/ui";
import { Action } from "@/entities/dashboard/types";
@@ -11,17 +12,24 @@ import { CompatibilityCard } from "../../cards";
import styles from "./CompatibilitySection.module.scss";
+interface CompatibilitySectionProps {
+ promise: Promise;
+ gridDisplayMode?: "vertical" | "horizontal";
+}
+
export default function CompatibilitySection({
promise,
-}: {
- promise: Promise;
-}) {
+ gridDisplayMode = "horizontal",
+}: CompatibilitySectionProps) {
const compatibilities = use(promise);
const columns = Math.ceil(compatibilities?.length / 2);
return (
-
+
{compatibilities.map(compatibility => (
;
+ gridDisplayMode?: "vertical" | "horizontal";
+}
+
export default function MeditationSection({
promise,
-}: {
- promise: Promise;
-}) {
+ gridDisplayMode = "horizontal",
+}: MeditationSectionProps) {
const meditations = use(promise);
const columns = meditations?.length;
return (
-
+
{meditations.map(meditation => (
-
-
+
+
))}
diff --git a/src/components/domains/breath/BreathPage/BreathPage.tsx b/src/components/domains/meditation/MeditationPage/MeditationPage.tsx
similarity index 79%
rename from src/components/domains/breath/BreathPage/BreathPage.tsx
rename to src/components/domains/meditation/MeditationPage/MeditationPage.tsx
index b772d86..4edc910 100644
--- a/src/components/domains/breath/BreathPage/BreathPage.tsx
+++ b/src/components/domains/meditation/MeditationPage/MeditationPage.tsx
@@ -8,17 +8,17 @@ import { ROUTES } from "@/shared/constants/client-routes";
import { StartBreathModalChild } from "..";
-interface BreathPageProps {
+interface MeditationPageProps {
id: string;
resultId: string;
}
-export default function BreathPage({ id, resultId }: BreathPageProps) {
+export default function MeditationPage({ id, resultId }: MeditationPageProps) {
const router = useRouter();
const { openModal, closeModal } = useFullScreenModal();
const handleBegin = useCallback(() => {
- router.push(ROUTES.breathResult(id, resultId));
+ router.push(ROUTES.meditationResult(id, resultId));
closeModal();
}, [closeModal, id, resultId, router]);
diff --git a/src/components/domains/breath/BreathResultPage/BreathResultPage.module.scss b/src/components/domains/meditation/MeditationResultPage/MeditationResultPage.module.scss
similarity index 100%
rename from src/components/domains/breath/BreathResultPage/BreathResultPage.module.scss
rename to src/components/domains/meditation/MeditationResultPage/MeditationResultPage.module.scss
diff --git a/src/components/domains/breath/BreathResultPage/BreathResultPage.tsx b/src/components/domains/meditation/MeditationResultPage/MeditationResultPage.tsx
similarity index 92%
rename from src/components/domains/breath/BreathResultPage/BreathResultPage.tsx
rename to src/components/domains/meditation/MeditationResultPage/MeditationResultPage.tsx
index 793a173..bbe2457 100644
--- a/src/components/domains/breath/BreathResultPage/BreathResultPage.tsx
+++ b/src/components/domains/meditation/MeditationResultPage/MeditationResultPage.tsx
@@ -9,18 +9,18 @@ import { Action } from "@/entities/dashboard/types";
import { useGenerationPolling } from "@/hooks/generation/useGenerationPolling";
import { useToast } from "@/providers/toast-provider";
-import styles from "./BreathResultPage.module.scss";
+import styles from "./MeditationResultPage.module.scss";
-interface BreathResultPageProps {
+interface MeditationResultPageProps {
id: string;
action: Action | undefined;
}
-export default function BreathResultPage({
+export default function MeditationResultPage({
id,
action,
-}: BreathResultPageProps) {
- const t = useTranslations("BreathResult");
+}: MeditationResultPageProps) {
+ const t = useTranslations("MeditationResult");
const { data, error, isLoading } = useGenerationPolling(id);
const { addToast } = useToast();
diff --git a/src/components/domains/breath/StartBreathModalChild/StartBreathModalChild.module.scss b/src/components/domains/meditation/StartBreathModalChild/StartBreathModalChild.module.scss
similarity index 100%
rename from src/components/domains/breath/StartBreathModalChild/StartBreathModalChild.module.scss
rename to src/components/domains/meditation/StartBreathModalChild/StartBreathModalChild.module.scss
diff --git a/src/components/domains/breath/StartBreathModalChild/StartBreathModalChild.tsx b/src/components/domains/meditation/StartBreathModalChild/StartBreathModalChild.tsx
similarity index 97%
rename from src/components/domains/breath/StartBreathModalChild/StartBreathModalChild.tsx
rename to src/components/domains/meditation/StartBreathModalChild/StartBreathModalChild.tsx
index 00069c0..99ed29a 100644
--- a/src/components/domains/breath/StartBreathModalChild/StartBreathModalChild.tsx
+++ b/src/components/domains/meditation/StartBreathModalChild/StartBreathModalChild.tsx
@@ -9,7 +9,7 @@ interface IStartBreathModalChildProps {
}
function StartBreathModalChild({ handleBegin }: IStartBreathModalChildProps) {
- const t = useTranslations("Breath");
+ const t = useTranslations("Meditation");
return (
diff --git a/src/components/domains/meditation/index.ts b/src/components/domains/meditation/index.ts
new file mode 100644
index 0000000..5b7e3ee
--- /dev/null
+++ b/src/components/domains/meditation/index.ts
@@ -0,0 +1,3 @@
+export { default as MeditationPage } from "./MeditationPage/MeditationPage";
+export { default as MeditationResultPage } from "./MeditationResultPage/MeditationResultPage";
+export { default as StartBreathModalChild } from "./StartBreathModalChild/StartBreathModalChild";
diff --git a/src/components/layout/Drawer/Drawer.tsx b/src/components/layout/Drawer/Drawer.tsx
index cbfbb1a..bfd1bf8 100644
--- a/src/components/layout/Drawer/Drawer.tsx
+++ b/src/components/layout/Drawer/Drawer.tsx
@@ -3,8 +3,7 @@
import Link from "next/link";
import clsx from "clsx";
-import { Button, Icon, Typography } from "@/components/ui";
-import { IconName } from "@/components/ui/Icon/Icon";
+import { Button, Icon, IconName, Typography } from "@/components/ui";
import { ROUTES } from "@/shared/constants/client-routes";
import styles from "./Drawer.module.scss";
diff --git a/src/components/layout/Header/Header.module.scss b/src/components/layout/Header/Header.module.scss
new file mode 100644
index 0000000..0f6fd6c
--- /dev/null
+++ b/src/components/layout/Header/Header.module.scss
@@ -0,0 +1,29 @@
+.header {
+ width: 100%;
+ min-height: 56px;
+ height: fit-content;
+ padding: 16px;
+ display: grid;
+ grid-template-columns: 1fr auto 1fr;
+ align-items: center;
+}
+
+.header > :first-child {
+ justify-self: start;
+}
+
+.header > :nth-child(2) {
+ justify-self: center;
+}
+
+.header > :nth-child(n + 3) {
+ justify-self: end;
+ display: inline-flex;
+ gap: 16px;
+}
+
+.menuButton.menuButton {
+ padding: 0;
+ width: fit-content;
+ background: none;
+}
diff --git a/src/components/layout/Header/Header.tsx b/src/components/layout/Header/Header.tsx
new file mode 100644
index 0000000..132c9d7
--- /dev/null
+++ b/src/components/layout/Header/Header.tsx
@@ -0,0 +1,36 @@
+"use client";
+
+import Link from "next/link";
+import clsx from "clsx";
+
+import { Button, Icon, IconName } from "@/components/ui";
+import { ROUTES } from "@/shared/constants/client-routes";
+
+import Logo from "../Logo/Logo";
+
+import styles from "./Header.module.scss";
+
+import { useDrawer } from "..";
+
+interface HeaderProps {
+ className?: string;
+}
+
+export default function Header({ className }: HeaderProps) {
+ const { open } = useDrawer();
+
+ return (
+
+ );
+}
diff --git a/src/components/layout/NavigationBar/NavigationBar.module.scss b/src/components/layout/NavigationBar/NavigationBar.module.scss
index 0f6fd6c..d372f40 100644
--- a/src/components/layout/NavigationBar/NavigationBar.module.scss
+++ b/src/components/layout/NavigationBar/NavigationBar.module.scss
@@ -1,29 +1,43 @@
-.header {
- width: 100%;
- min-height: 56px;
- height: fit-content;
- padding: 16px;
- display: grid;
- grid-template-columns: 1fr auto 1fr;
+.container {
+ width: calc(100% - 32px);
+ max-width: 400px;
+ position: fixed;
+ bottom: calc(0dvh + 14px);
+ left: 50%;
+ z-index: 9995;
+ transform: translateX(-50%);
+ display: flex;
align-items: center;
+ justify-content: space-around;
+ // gap: 40px;
+ background-color: #e5e7eb;
+ border-radius: 24px;
+ padding: 16px 24px 12px;
}
-.header > :first-child {
- justify-self: start;
-}
+.item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 5px;
+ position: relative;
-.header > :nth-child(2) {
- justify-self: center;
-}
+ & .badge {
+ position: absolute;
+ bottom: 7px;
+ left: 17px;
+ }
-.header > :nth-child(n + 3) {
- justify-self: end;
- display: inline-flex;
- gap: 16px;
-}
+ & > .label {
+ font-size: 11px;
+ line-height: 14px;
+ color: #8a8d93;
+ }
-.menuButton.menuButton {
- padding: 0;
- width: fit-content;
- background: none;
+ &.active {
+ & > .label {
+ color: #007aff;
+ }
+ }
}
diff --git a/src/components/layout/NavigationBar/NavigationBar.tsx b/src/components/layout/NavigationBar/NavigationBar.tsx
index 6cf28a5..1c7b986 100644
--- a/src/components/layout/NavigationBar/NavigationBar.tsx
+++ b/src/components/layout/NavigationBar/NavigationBar.tsx
@@ -1,37 +1,51 @@
"use client";
import Link from "next/link";
+import { usePathname } from "next/navigation";
+import { useLocale } from "next-intl";
import clsx from "clsx";
-import { Button, Icon } from "@/components/ui";
-import { IconName } from "@/components/ui/Icon/Icon";
+import { Badge, Icon, Typography } from "@/components/ui";
import { ROUTES } from "@/shared/constants/client-routes";
-
-import Logo from "../Logo/Logo";
+import { navItems } from "@/shared/constants/navigation";
+import { stripLocale } from "@/shared/utils/path";
import styles from "./NavigationBar.module.scss";
-import { useDrawer } from "..";
-
-interface NavigationBarProps {
- className?: string;
-}
-
-export default function NavigationBar({ className }: NavigationBarProps) {
- const { open } = useDrawer();
+export default function NavigationBar() {
+ const pathname = usePathname();
+ const locale = useLocale();
+ const pathnameWithoutLocale = stripLocale(pathname, locale);
return (
-
+
);
}
diff --git a/src/components/layout/index.ts b/src/components/layout/index.ts
index 24f5dfa..c711061 100644
--- a/src/components/layout/index.ts
+++ b/src/components/layout/index.ts
@@ -1,4 +1,4 @@
export { DrawerProvider, useDrawer } from "./Drawer/DrawerContext";
+export { default as Header } from "./Header/Header";
export { default as Logo } from "./Logo/Logo";
-export { default as NavigationBar } from "./NavigationBar/NavigationBar";
export { default as StepperBar } from "./StepperBar/StepperBar";
diff --git a/src/components/ui/Badge/Badge.module.scss b/src/components/ui/Badge/Badge.module.scss
new file mode 100644
index 0000000..74c164c
--- /dev/null
+++ b/src/components/ui/Badge/Badge.module.scss
@@ -0,0 +1,11 @@
+.badge {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 4px;
+ min-width: fit-content;
+ min-height: fit-content;
+ aspect-ratio: 1/1;
+ border-radius: 50%;
+ background-color: #ff0028;
+}
diff --git a/src/components/ui/Badge/Badge.tsx b/src/components/ui/Badge/Badge.tsx
new file mode 100644
index 0000000..0b37787
--- /dev/null
+++ b/src/components/ui/Badge/Badge.tsx
@@ -0,0 +1,12 @@
+import clsx from "clsx";
+
+import styles from "./Badge.module.scss";
+
+interface BadgeProps {
+ children: React.ReactNode;
+ className?: string;
+}
+
+export default function Badge({ children, className }: BadgeProps) {
+ return {children}
;
+}
diff --git a/src/components/ui/Icon/Icon.tsx b/src/components/ui/Icon/Icon.tsx
index 8e11fcb..cc853de 100644
--- a/src/components/ui/Icon/Icon.tsx
+++ b/src/components/ui/Icon/Icon.tsx
@@ -1,14 +1,21 @@
import { CSSProperties, ReactNode } from "react";
import clsx from "clsx";
-import ArticleIcon from "./icons/Article";
-import ChevronIcon from "./icons/Chevron";
-import CrossIcon from "./icons/Cross";
-import MenuIcon from "./icons/Menu";
-import NotificationIcon from "./icons/Notification";
-import SearchIcon from "./icons/Search";
-import StarIcon from "./icons/Star";
-import VideoIcon from "./icons/Video";
+import {
+ ArticleIcon,
+ ChatIcon,
+ ChevronIcon,
+ ClipboardIcon,
+ CrossIcon,
+ HeartIcon,
+ HomeIcon,
+ LeafIcon,
+ MenuIcon,
+ NotificationIcon,
+ SearchIcon,
+ StarIcon,
+ VideoIcon,
+} from "./icons";
export enum IconName {
Notification,
@@ -19,6 +26,11 @@ export enum IconName {
Chevron,
Star,
Cross,
+ Home,
+ Chat,
+ Clipboard,
+ Heart,
+ Leaf,
}
const icons: Record<
@@ -33,6 +45,11 @@ const icons: Record<
[IconName.Chevron]: ChevronIcon,
[IconName.Star]: StarIcon,
[IconName.Cross]: CrossIcon,
+ [IconName.Home]: HomeIcon,
+ [IconName.Chat]: ChatIcon,
+ [IconName.Clipboard]: ClipboardIcon,
+ [IconName.Heart]: HeartIcon,
+ [IconName.Leaf]: LeafIcon,
};
export type IconProps = {
diff --git a/src/components/ui/Icon/icons/Chat.tsx b/src/components/ui/Icon/icons/Chat.tsx
new file mode 100644
index 0000000..9c86f14
--- /dev/null
+++ b/src/components/ui/Icon/icons/Chat.tsx
@@ -0,0 +1,37 @@
+import { SVGProps } from "react";
+
+export default function ChatIcon(props: SVGProps) {
+ return (
+
+ );
+}
diff --git a/src/components/ui/Icon/icons/Clipboard.tsx b/src/components/ui/Icon/icons/Clipboard.tsx
new file mode 100644
index 0000000..2737005
--- /dev/null
+++ b/src/components/ui/Icon/icons/Clipboard.tsx
@@ -0,0 +1,47 @@
+import { SVGProps } from "react";
+
+export default function ClipboardIcon(props: SVGProps) {
+ return (
+
+ );
+}
diff --git a/src/components/ui/Icon/icons/Heart.tsx b/src/components/ui/Icon/icons/Heart.tsx
new file mode 100644
index 0000000..0183c8f
--- /dev/null
+++ b/src/components/ui/Icon/icons/Heart.tsx
@@ -0,0 +1,36 @@
+import { SVGProps } from "react";
+
+export default function HeartIcon(props: SVGProps) {
+ return (
+
+ );
+}
diff --git a/src/components/ui/Icon/icons/Home.tsx b/src/components/ui/Icon/icons/Home.tsx
new file mode 100644
index 0000000..14ecb2a
--- /dev/null
+++ b/src/components/ui/Icon/icons/Home.tsx
@@ -0,0 +1,37 @@
+import { SVGProps } from "react";
+
+export default function HomeIcon(props: SVGProps) {
+ return (
+
+ );
+}
diff --git a/src/components/ui/Icon/icons/Leaf.tsx b/src/components/ui/Icon/icons/Leaf.tsx
new file mode 100644
index 0000000..6021116
--- /dev/null
+++ b/src/components/ui/Icon/icons/Leaf.tsx
@@ -0,0 +1,36 @@
+import { SVGProps } from "react";
+
+export default function Leaf(props: SVGProps) {
+ return (
+
+ );
+}
diff --git a/src/components/ui/Icon/icons/index.ts b/src/components/ui/Icon/icons/index.ts
new file mode 100644
index 0000000..f8dc85c
--- /dev/null
+++ b/src/components/ui/Icon/icons/index.ts
@@ -0,0 +1,13 @@
+export { default as ArticleIcon } from "./Article";
+export { default as ChatIcon } from "./Chat";
+export { default as ChevronIcon } from "./Chevron";
+export { default as ClipboardIcon } from "./Clipboard";
+export { default as CrossIcon } from "./Cross";
+export { default as HeartIcon } from "./Heart";
+export { default as HomeIcon } from "./Home";
+export { default as LeafIcon } from "./Leaf";
+export { default as MenuIcon } from "./Menu";
+export { default as NotificationIcon } from "./Notification";
+export { default as SearchIcon } from "./Search";
+export { default as StarIcon } from "./Star";
+export { default as VideoIcon } from "./Video";
diff --git a/src/components/ui/IconLabel/IconLabel.tsx b/src/components/ui/IconLabel/IconLabel.tsx
index 6c0c568..558b6f6 100644
--- a/src/components/ui/IconLabel/IconLabel.tsx
+++ b/src/components/ui/IconLabel/IconLabel.tsx
@@ -1,10 +1,10 @@
import { ReactNode } from "react";
import clsx from "clsx";
-import Icon, { IconProps } from "../Icon/Icon";
-
import styles from "./IconLabel.module.scss";
+import { Icon, IconProps } from "..";
+
export type IconLabelProps = {
iconProps: IconProps;
children: ReactNode;
diff --git a/src/components/ui/MetaLabel/MetaLabel.tsx b/src/components/ui/MetaLabel/MetaLabel.tsx
index 1331b18..f844d1e 100644
--- a/src/components/ui/MetaLabel/MetaLabel.tsx
+++ b/src/components/ui/MetaLabel/MetaLabel.tsx
@@ -1,11 +1,12 @@
import { ReactNode } from "react";
-import IconLabel, { IconLabelProps } from "../IconLabel/IconLabel";
import Typography from "../Typography/Typography";
import styles from "./MetaLabel.module.scss";
-export type MetaLabelProps = {
+import { IconLabel, IconLabelProps } from "..";
+
+type MetaLabelProps = {
iconLabelProps: IconLabelProps;
children: ReactNode;
};
diff --git a/src/components/ui/Modal/Modal.tsx b/src/components/ui/Modal/Modal.tsx
index d9af9b9..994c1d3 100644
--- a/src/components/ui/Modal/Modal.tsx
+++ b/src/components/ui/Modal/Modal.tsx
@@ -3,11 +3,9 @@
import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
import clsx from "clsx";
-import { IconName } from "../Icon/Icon";
-
import styles from "./Modal.module.scss";
-import { Button, Icon } from "..";
+import { Button, Icon, IconName } from "..";
interface ModalProps {
children: ReactNode;
diff --git a/src/components/ui/Stars/Stars.tsx b/src/components/ui/Stars/Stars.tsx
index 92301d4..96af383 100644
--- a/src/components/ui/Stars/Stars.tsx
+++ b/src/components/ui/Stars/Stars.tsx
@@ -1,9 +1,9 @@
import clsx from "clsx";
-import Icon, { IconName } from "../Icon/Icon";
-
import styles from "./Stars.module.scss";
+import { Icon, IconName } from "..";
+
interface StarsProps {
rating?: number;
size?: number;
diff --git a/src/components/ui/index.ts b/src/components/ui/index.ts
index a25f831..02238ef 100644
--- a/src/components/ui/index.ts
+++ b/src/components/ui/index.ts
@@ -1,3 +1,4 @@
+export { default as Badge } from "./Badge/Badge";
export { default as Button } from "./Button/Button";
export { default as Card } from "./Card/Card";
export { default as CircleArrow } from "./CircleArrow/CircleArrow";
@@ -5,8 +6,11 @@ export { default as EmailInput } from "./EmailInput/EmailInput";
export { default as FullScreenBlurModal } from "./FullScreenBlurModal/FullScreenBlurModal";
export { default as GPTAnimationText } from "./GPTAnimationText/GPTAnimationText";
export { default as Grid } from "./Grid/Grid";
-export { default as Icon } from "./Icon/Icon";
-export { default as IconLabel } from "./IconLabel/IconLabel";
+export { default as Icon, IconName, type IconProps } from "./Icon/Icon";
+export {
+ default as IconLabel,
+ type IconLabelProps,
+} from "./IconLabel/IconLabel";
export { default as MetaLabel } from "./MetaLabel/MetaLabel";
export { default as Modal } from "./Modal/Modal";
export { default as NameInput } from "./NameInput/NameInput";
diff --git a/src/components/widgets/DatePicker/DatePicker.tsx b/src/components/widgets/DatePicker/DatePicker.tsx
index cabfaf8..6219e15 100644
--- a/src/components/widgets/DatePicker/DatePicker.tsx
+++ b/src/components/widgets/DatePicker/DatePicker.tsx
@@ -1,7 +1,7 @@
"use client";
import { useEffect, useMemo, useState } from "react";
-import { useTranslations } from "next-intl";
+import { useLocale, useTranslations } from "next-intl";
import { Typography } from "@/components/ui";
import { SelectInput } from "@/components/ui/SelectInput/SelectInput";
@@ -20,9 +20,7 @@ const isValidDate = (year: number, month: number, day: number) => {
// Упрощенное определение порядка полей даты на основе локали.
// В реальном приложении здесь лучше использовать данные из next-intl.
-const getDateInputLocaleFormat = (): ("d" | "m" | "y")[] => {
- const locale =
- typeof navigator !== "undefined" ? navigator.language : "en-US";
+const getDateInputLocaleFormat = (locale: string): ("d" | "m" | "y")[] => {
const format = new Intl.DateTimeFormat(locale).format(new Date(2001, 1, 3)); // Используем 3/Feb/2001
if (/^3.*2/.test(format)) return ["d", "m", "y"]; // 3/2/2001 -> d/m/y
if (/^2.*3/.test(format)) return ["m", "d", "y"]; // 2/3/2001 -> m/d/y
@@ -49,6 +47,8 @@ export default function DatePicker({
onBlur,
}: DatePickerProps) {
const t = useTranslations("DatePicker");
+ const locale = useLocale();
+
const [year, setYear] = useState("");
const [month, setMonth] = useState("");
const [day, setDay] = useState("");
@@ -110,7 +110,10 @@ export default function DatePicker({
}));
}, [year, month]);
- const localeFormat = useMemo(() => getDateInputLocaleFormat(), []);
+ const localeFormat = useMemo(
+ () => getDateInputLocaleFormat(locale),
+ [locale]
+ );
const inputs = {
d: (
diff --git a/src/middleware.ts b/src/middleware.ts
index 56226f0..3445948 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -39,7 +39,7 @@ const intlMiddleware = createMiddleware(routing);
export default async function middleware(request: NextRequest) {
const authResponse = await createAuthMiddleware()(request);
- if (authResponse.status !== 200) {
+ if (authResponse.status !== 200 && process.env.NODE_ENV === "production") {
return authResponse;
}
diff --git a/src/shared/constants/client-routes.ts b/src/shared/constants/client-routes.ts
index 9777ba9..e1e5de2 100644
--- a/src/shared/constants/client-routes.ts
+++ b/src/shared/constants/client-routes.ts
@@ -3,8 +3,8 @@ const ROOT_ROUTE = "/";
const profilePrefix = "profile";
const retainingFunnelPrefix = "retaining";
-const createRoute = (segments: string[]): string => {
- return ROOT_ROUTE + segments.join("/");
+const createRoute = (segments: Array): string => {
+ return ROOT_ROUTE + segments.filter(Boolean).join("/");
};
export const ROUTES = {
@@ -13,13 +13,16 @@ export const ROUTES = {
// Auth
authCallback: () => createRoute(["auth", "callback"]),
- // Breath
- breath: (id: string) => createRoute(["breath", id]),
- breathResult: (id: string, resultId: string) =>
- createRoute(["breath", id, "result", resultId]),
+ // Advisers
+ advisers: () => createRoute(["advisers"]),
+
+ // Meditation
+ meditation: (id?: string) => createRoute(["meditation", id]),
+ meditationResult: (id: string, resultId: string) =>
+ createRoute(["meditation", id, "result", resultId]),
// Compatibility
- compatibility: (id: string) => createRoute(["compatibility", id]),
+ compatibility: (id?: string) => createRoute(["compatibility", id]),
compatibilityResult: (id: string, resultId: string) =>
createRoute(["compatibility", id, "result", resultId]),
@@ -56,4 +59,13 @@ export const ROUTES = {
payment: () => createRoute(["payment"]),
paymentSuccess: () => createRoute(["payment", "success"]),
paymentFailed: () => createRoute(["payment", "failed"]),
+
+ // Chat
+ chat: () => createRoute(["chat"]),
+
+ // // Compatibility
+ // compatibilities: () => createRoute(["compatibilities"]),
+
+ // // Meditation
+ // meditations: () => createRoute(["meditations"]),
};
diff --git a/src/shared/constants/navigation.tsx b/src/shared/constants/navigation.tsx
new file mode 100644
index 0000000..59e7e49
--- /dev/null
+++ b/src/shared/constants/navigation.tsx
@@ -0,0 +1,45 @@
+import { IconName } from "@/components/ui";
+
+import { ROUTES } from "./client-routes";
+
+interface NavItem {
+ key: string;
+ label: string;
+ icon: IconName;
+ href: string;
+ badge?: number;
+}
+
+export const navItems: NavItem[] = [
+ {
+ key: "home",
+ label: "Home",
+ icon: IconName.Home,
+ href: ROUTES.home(),
+ },
+ {
+ key: "chat",
+ label: "Chat",
+ icon: IconName.Chat,
+ href: ROUTES.chat(),
+ badge: 12,
+ },
+ {
+ key: "advisers",
+ label: "Advi...",
+ icon: IconName.Clipboard,
+ href: ROUTES.advisers(),
+ },
+ {
+ key: "compatibility",
+ label: "Comp...",
+ icon: IconName.Heart,
+ href: ROUTES.compatibility(),
+ },
+ {
+ key: "meditation",
+ label: "Medi...",
+ icon: IconName.Leaf,
+ href: ROUTES.meditation(),
+ },
+];
diff --git a/src/shared/utils/path.ts b/src/shared/utils/path.ts
new file mode 100644
index 0000000..3e16ea5
--- /dev/null
+++ b/src/shared/utils/path.ts
@@ -0,0 +1,6 @@
+export function stripLocale(pathname: string, locale: string) {
+ if (pathname.startsWith(`/${locale}`)) {
+ return pathname.slice(locale.length + 1) || "/";
+ }
+ return pathname;
+}