feat: actions page for mobiles

This commit is contained in:
2025-10-07 09:48:05 +04:00
parent 7b0b3bc529
commit 428a6aca82
11 changed files with 154 additions and 17 deletions

View File

@ -0,0 +1,15 @@
.link {
width: 100%;
border-radius: var(--mantine-radius-lg);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
@mixin light {
color: var(--mantine-color-gray-7);
}
@mixin dark {
color: var(--mantine-color-dark-0);
}
}

View File

@ -0,0 +1,36 @@
import { FC } from "react";
import Link from "next/link";
import { Button, Stack, Text } from "@mantine/core";
import ThemeIcon from "@/components/ui/ThemeIcon/ThemeIcon";
import LinkData from "@/types/LinkData";
import styles from "./Action.module.css";
type Props = {
linkData: LinkData;
};
const Action: FC<Props> = ({ linkData }) => {
return (
<Link
href={linkData.href}
className={styles.link}>
<Button
w={"100%"}
h={"100px"}
variant={"default"}>
<Stack
px={"xs"}
w={"100%"}
align={"center"}
gap={"xs"}>
<ThemeIcon size={"sm"}>
<linkData.icon />
</ThemeIcon>
<Text>{linkData.label}</Text>
</Stack>
</Button>
</Link>
);
};
export default Action;

View File

@ -0,0 +1,48 @@
"use client";
import { useMemo } from "react";
import { SimpleGrid, Stack } from "@mantine/core";
import Action from "@/app/actions/components/Action/Action";
import mobileButtonsData from "@/app/actions/data/mobileButtonsData";
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
import PageBlock from "@/components/layout/PageBlock/PageBlock";
import ProjectSelect from "@/components/selects/ProjectSelect/ProjectSelect";
const PageBody = () => {
const { selectedProject, setSelectedProjectId, projects, modulesSet } =
useProjectsContext();
const filteredMobileButtonsData = useMemo(
() =>
mobileButtonsData.filter(
link => !link.moduleName || modulesSet.has(link.moduleName)
),
[modulesSet]
);
return (
<PageBlock fullScreenMobile>
<Stack p={"xs"}>
<ProjectSelect
onChange={project =>
setSelectedProjectId(project?.id ?? null)
}
value={selectedProject}
data={projects}
/>
<SimpleGrid
type={"container"}
cols={2}>
{filteredMobileButtonsData.map((data, index) => (
<Action
linkData={data}
key={index}
/>
))}
</SimpleGrid>
</Stack>
</PageBlock>
);
};
export default PageBody;

View File

@ -0,0 +1,26 @@
import { IconColumns, IconFileBarcode, IconUsers } from "@tabler/icons-react";
import { ModuleNames } from "@/modules/modules";
import LinkData from "@/types/LinkData";
const mobileButtonsData: LinkData[] = [
{
icon: IconUsers,
label: "Клиенты",
href: "/clients",
moduleName: ModuleNames.CLIENTS,
},
{
icon: IconColumns,
label: "Услуги",
href: "/services",
moduleName: ModuleNames.FULFILLMENT_BASE,
},
{
icon: IconFileBarcode,
label: "Шаблоны штрихкодов",
href: "/barcode-templates",
moduleName: ModuleNames.FULFILLMENT_BASE,
},
];
export default mobileButtonsData;

19
src/app/actions/page.tsx Normal file
View File

@ -0,0 +1,19 @@
import { Suspense } from "react";
import { Center, Loader } from "@mantine/core";
import PageContainer from "@/components/layout/PageContainer/PageContainer";
import PageBody from "./components/PageBody/PageBody";
export default async function ActionsPage() {
return (
<Suspense
fallback={
<Center h="50vh">
<Loader size="lg" />
</Center>
}>
<PageContainer>
<PageBody />
</PageContainer>
</Suspense>
);
}

View File

@ -1,10 +1,10 @@
import {
IconCalendarWeekFilled,
IconCircleDotted,
IconLayoutGrid,
IconLayoutKanban,
IconTable,
} from "@tabler/icons-react";
import LinkData from "@/components/layout/Navbar/types/LinkData";
import LinkData from "@/types/LinkData";
const buttonsData: LinkData[] = [
{
@ -23,9 +23,9 @@ const buttonsData: LinkData[] = [
href: "/deals?view=schedule",
},
{
icon: IconCircleDotted,
label: "Label 3",
href: "/hihihaha",
icon: IconLayoutGrid,
label: "Действия",
href: "/actions",
},
];

View File

@ -1,9 +0,0 @@
import { IconPlus } from "@tabler/icons-react";
type LinkData = {
icon: typeof IconPlus;
label: string;
href: string;
};
export default LinkData;

View File

@ -5,10 +5,12 @@ import { usePathname, useRouter } from "next/navigation";
import { Group, Stack, Text } from "@mantine/core";
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
import ThemeIcon from "@/components/ui/ThemeIcon/ThemeIcon";
import useIsMobile from "@/hooks/utils/useIsMobile";
import linksData from "../data/linksData";
import NavbarClickable from "./NavbarClickable";
const NavbarLinks = () => {
const isMobile = useIsMobile();
const pathname = usePathname();
const router = useRouter();
const { modulesSet, selectedProject } = useProjectsContext();
@ -21,7 +23,7 @@ const NavbarLinks = () => {
);
useEffect(() => {
if (pathname !== "/deals") router.push("/deals");
if (!isMobile && pathname !== "/deals") router.push("/deals");
}, [selectedProject]);
return (

View File

@ -4,8 +4,8 @@ import {
IconLayoutKanban,
IconUsers,
} from "@tabler/icons-react";
import LinkData from "@/components/layout/Navbar/types/LinkData";
import { ModuleNames } from "@/modules/modules";
import LinkData from "@/types/LinkData";
const linksData: LinkData[] = [
{

View File

@ -51,11 +51,11 @@ const ClientDataForm: FC = () => {
flex={1}
/>
<TextInput
disabled
placeholder={"Наименование компании"}
label={"Наименование компании"}
{...form.getInputProps("companyName")}
flex={1}
disabled={isEditorDisabled}
/>
</FormFlexRow>
<FormFlexRow>