From 4323695069835a668c6f819b98b854743011371e Mon Sep 17 00:00:00 2001 From: AlexSserb Date: Thu, 28 Aug 2025 11:00:41 +0400 Subject: [PATCH] feat: select view buttons --- .../desktop/TopToolPanel/TopToolPanel.tsx | 28 +++++++++++++++ .../ViewSelectButton.module.css | 9 +++++ .../ViewSelectButton/ViewSelectButton.tsx | 34 +++++++++++++++++++ .../desktop/ViewSelector/ViewSelector.tsx | 25 ++++++++++++++ .../shared/Boards/Boards.module.css | 2 +- .../components/shared/PageBody/PageBody.tsx | 28 +++++++++++++++ .../StatusColumnWrapper.module.css | 2 +- src/app/deals/contexts/ViewContext.tsx | 23 +++++++++++++ src/app/deals/page.tsx | 19 +++++------ .../layout/PageBlock/PageBlock.module.css | 7 ---- .../PageContainer/PageContainer.module.css | 3 +- .../SmallPageBlock/SmallPageBlock.module.css | 33 ++++++++++++++++++ .../layout/SmallPageBlock/SmallPageBlock.tsx | 24 +++++++++++++ src/modals/EnterNameModal/EnterNameModal.tsx | 5 ++- 14 files changed, 220 insertions(+), 22 deletions(-) create mode 100644 src/app/deals/components/desktop/TopToolPanel/TopToolPanel.tsx create mode 100644 src/app/deals/components/desktop/ViewSelectButton/ViewSelectButton.module.css create mode 100644 src/app/deals/components/desktop/ViewSelectButton/ViewSelectButton.tsx create mode 100644 src/app/deals/components/desktop/ViewSelector/ViewSelector.tsx create mode 100644 src/app/deals/components/shared/PageBody/PageBody.tsx create mode 100644 src/app/deals/contexts/ViewContext.tsx create mode 100644 src/components/layout/SmallPageBlock/SmallPageBlock.module.css create mode 100644 src/components/layout/SmallPageBlock/SmallPageBlock.tsx diff --git a/src/app/deals/components/desktop/TopToolPanel/TopToolPanel.tsx b/src/app/deals/components/desktop/TopToolPanel/TopToolPanel.tsx new file mode 100644 index 0000000..a64d375 --- /dev/null +++ b/src/app/deals/components/desktop/TopToolPanel/TopToolPanel.tsx @@ -0,0 +1,28 @@ +"use client"; + +import { Group } from "@mantine/core"; +import ViewSelector from "@/app/deals/components/desktop/ViewSelector/ViewSelector"; +import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext"; +import ProjectSelect from "@/components/selects/ProjectSelect/ProjectSelect"; +import useIsMobile from "@/hooks/utils/useIsMobile"; + +const TopToolPanel = () => { + const { projects, setSelectedProjectId, selectedProject } = + useProjectsContext(); + const isMobile = useIsMobile(); + + if (isMobile) return; + + return ( + + + value && setSelectedProjectId(value.id)} + /> + + ); +}; + +export default TopToolPanel; diff --git a/src/app/deals/components/desktop/ViewSelectButton/ViewSelectButton.module.css b/src/app/deals/components/desktop/ViewSelectButton/ViewSelectButton.module.css new file mode 100644 index 0000000..b3ff25b --- /dev/null +++ b/src/app/deals/components/desktop/ViewSelectButton/ViewSelectButton.module.css @@ -0,0 +1,9 @@ +.container { + width: 100%; + border-radius: var(--mantine-radius-xl); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + padding: var(--mantine-spacing-xs); +} diff --git a/src/app/deals/components/desktop/ViewSelectButton/ViewSelectButton.tsx b/src/app/deals/components/desktop/ViewSelectButton/ViewSelectButton.tsx new file mode 100644 index 0000000..02d9cea --- /dev/null +++ b/src/app/deals/components/desktop/ViewSelectButton/ViewSelectButton.tsx @@ -0,0 +1,34 @@ +"use client"; + +import { FC, PropsWithChildren } from "react"; +import { Button } from "@mantine/core"; +import { useViewContext, View } from "@/app/deals/contexts/ViewContext"; +import SmallPageBlock from "@/components/layout/SmallPageBlock/SmallPageBlock"; +import style from "./ViewSelectButton.module.css"; + +type Props = { + viewName: View; +}; + +const ViewSelectButton: FC> = ({ + viewName, + children, +}) => { + const { view, setView } = useViewContext(); + + return ( + + + + ); +}; + +export default ViewSelectButton; diff --git a/src/app/deals/components/desktop/ViewSelector/ViewSelector.tsx b/src/app/deals/components/desktop/ViewSelector/ViewSelector.tsx new file mode 100644 index 0000000..0029b93 --- /dev/null +++ b/src/app/deals/components/desktop/ViewSelector/ViewSelector.tsx @@ -0,0 +1,25 @@ +import { + IconCalendarWeekFilled, + IconLayoutDashboard, + IconMenu2, +} from "@tabler/icons-react"; +import { Group } from "@mantine/core"; +import ViewSelectButton from "@/app/deals/components/desktop/ViewSelectButton/ViewSelectButton"; + +const ViewSelector = () => { + return ( + + + + + + + + + + + + ); +}; + +export default ViewSelector; diff --git a/src/app/deals/components/shared/Boards/Boards.module.css b/src/app/deals/components/shared/Boards/Boards.module.css index 70b1827..390a722 100644 --- a/src/app/deals/components/shared/Boards/Boards.module.css +++ b/src/app/deals/components/shared/Boards/Boards.module.css @@ -1,6 +1,6 @@ .container { @media (min-width: 48em) { - max-width: calc(100vw - 450px); + max-width: calc(100vw - 210px - var(--mantine-spacing-md)); } @media (max-width: 48em) { max-width: 100vw; diff --git a/src/app/deals/components/shared/PageBody/PageBody.tsx b/src/app/deals/components/shared/PageBody/PageBody.tsx new file mode 100644 index 0000000..5d7274e --- /dev/null +++ b/src/app/deals/components/shared/PageBody/PageBody.tsx @@ -0,0 +1,28 @@ +"use client"; + +import { Space } from "@mantine/core"; +import MainBlockHeader from "@/app/deals/components/mobile/MainBlockHeader/MainBlockHeader"; +import Funnel from "@/app/deals/components/shared/Funnel/Funnel"; +import { DealsContextProvider } from "@/app/deals/contexts/DealsContext"; +import { useViewContext } from "@/app/deals/contexts/ViewContext"; + +const PageBody = () => { + const { view } = useViewContext(); + + if (view === "board") + return ( + <> + + + + + + + ); + + if (view === "table") return <>-; + + return <>-; +}; + +export default PageBody; diff --git a/src/app/deals/components/shared/StatusColumnWrapper/StatusColumnWrapper.module.css b/src/app/deals/components/shared/StatusColumnWrapper/StatusColumnWrapper.module.css index 0fd6c08..a37f91f 100644 --- a/src/app/deals/components/shared/StatusColumnWrapper/StatusColumnWrapper.module.css +++ b/src/app/deals/components/shared/StatusColumnWrapper/StatusColumnWrapper.module.css @@ -1,6 +1,6 @@ .container { - height: calc(100vh - 150px); + height: calc(100vh - 210px); @media (max-width: 48em) { width: 80vw; height: calc(100vh - 215px); diff --git a/src/app/deals/contexts/ViewContext.tsx b/src/app/deals/contexts/ViewContext.tsx new file mode 100644 index 0000000..f59cf20 --- /dev/null +++ b/src/app/deals/contexts/ViewContext.tsx @@ -0,0 +1,23 @@ +"use client"; + +import { useState } from "react"; +import makeContext from "@/lib/contextFactory/contextFactory"; + +export type View = "board" | "table" | "schedule"; + +type ViewContextState = { + view: View; + setView: (view: View) => void; +}; + +const useViewContextState = (): ViewContextState => { + const [view, setView] = useState("board"); + + return { + view, + setView, + }; +}; + +export const [ViewContextProvider, useViewContext] = + makeContext(useViewContextState, "View"); diff --git a/src/app/deals/page.tsx b/src/app/deals/page.tsx index fefadd3..dd17a08 100644 --- a/src/app/deals/page.tsx +++ b/src/app/deals/page.tsx @@ -3,12 +3,11 @@ import { HydrationBoundary, QueryClient, } from "@tanstack/react-query"; -import { Space } from "@mantine/core"; -import Funnel from "@/app/deals/components/shared/Funnel/Funnel"; -import Header from "@/app/deals/components/shared/Header/Header"; +import PageBody from "@/app/deals/components/shared/PageBody/PageBody"; import { BoardsContextProvider } from "@/app/deals/contexts/BoardsContext"; import { ProjectsContextProvider } from "@/app/deals/contexts/ProjectsContext"; import { StatusesContextProvider } from "@/app/deals/contexts/StatusesContext"; +import { ViewContextProvider } from "@/app/deals/contexts/ViewContext"; import PageBlock from "@/components/layout/PageBlock/PageBlock"; import PageContainer from "@/components/layout/PageContainer/PageContainer"; import { @@ -16,7 +15,7 @@ import { getProjectsOptions, } from "@/lib/client/@tanstack/react-query.gen"; import { combineProviders } from "@/utils/combineProviders"; -import { DealsContextProvider } from "./contexts/DealsContext"; +import TopToolPanel from "./components/desktop/TopToolPanel/TopToolPanel"; async function prefetchData() { const queryClient = new QueryClient(); @@ -39,18 +38,16 @@ export default async function DealsPage() { [HydrationBoundary, { state: dehydrate(queryClient) }], [ProjectsContextProvider], [BoardsContextProvider], - [StatusesContextProvider] + [StatusesContextProvider], + [ViewContextProvider] ); return ( - -
- - - - + + + diff --git a/src/components/layout/PageBlock/PageBlock.module.css b/src/components/layout/PageBlock/PageBlock.module.css index 6aa3a1f..e7e9eda 100644 --- a/src/components/layout/PageBlock/PageBlock.module.css +++ b/src/components/layout/PageBlock/PageBlock.module.css @@ -18,13 +18,6 @@ } } -.mobile-margin-height { - height: var(--page-height); - @media (min-width: 48em) { - margin: var(--mantine-spacing-md); - } -} - .container-full-height { min-height: var(--page-height); height: var(--page-height); diff --git a/src/components/layout/PageContainer/PageContainer.module.css b/src/components/layout/PageContainer/PageContainer.module.css index 0c926b6..5d21c11 100644 --- a/src/components/layout/PageContainer/PageContainer.module.css +++ b/src/components/layout/PageContainer/PageContainer.module.css @@ -5,6 +5,7 @@ background-color: transparent; @media (min-width: 48em) { - gap: rem(10); + gap: var(--mantine-spacing-md); + padding: var(--mantine-spacing-md); } } diff --git a/src/components/layout/SmallPageBlock/SmallPageBlock.module.css b/src/components/layout/SmallPageBlock/SmallPageBlock.module.css new file mode 100644 index 0000000..dd53857 --- /dev/null +++ b/src/components/layout/SmallPageBlock/SmallPageBlock.module.css @@ -0,0 +1,33 @@ + +.container { + border-radius: var(--mantine-radius-lg); + + @mixin dark { + background-color: var(--mantine-color-dark-7-5); + box-shadow: var(--dark-shadow); + } + @mixin light { + background-color: var(--color-light-whitesmoke); + box-shadow: var(--light-shadow); + } +} + +.container-active { + @mixin dark { + color: dodgerblue; + } + @mixin light { + background-color: var(--color-light-aqua); + box-shadow: var(--light-thick-shadow); + } +} + +.container:hover { + @mixin dark { + box-shadow: var(--dark-thick-shadow); + } + @mixin light { + background-color: var(--color-light-aqua); + box-shadow: var(--light-thick-shadow); + } +} diff --git a/src/components/layout/SmallPageBlock/SmallPageBlock.tsx b/src/components/layout/SmallPageBlock/SmallPageBlock.tsx new file mode 100644 index 0000000..f0021ea --- /dev/null +++ b/src/components/layout/SmallPageBlock/SmallPageBlock.tsx @@ -0,0 +1,24 @@ +import { CSSProperties, FC, ReactNode } from "react"; +import classNames from "classnames"; +import { Box } from "@mantine/core"; +import styles from "@/components/layout/SmallPageBlock/SmallPageBlock.module.css"; + +type Props = { + children: ReactNode; + style?: CSSProperties; + active?: boolean; +}; + +const SmallPageBlock: FC = ({ children, style, active = false }) => { + return ( + + {children} + + ); +}; +export default SmallPageBlock; diff --git a/src/modals/EnterNameModal/EnterNameModal.tsx b/src/modals/EnterNameModal/EnterNameModal.tsx index f77966b..7a803a8 100644 --- a/src/modals/EnterNameModal/EnterNameModal.tsx +++ b/src/modals/EnterNameModal/EnterNameModal.tsx @@ -37,7 +37,10 @@ const EnterNameModal = ({ - +