This commit is contained in:
2025-06-10 16:58:54 +05:00
parent f204767e0a
commit e3eea86e28
8 changed files with 166 additions and 87 deletions
+2 -2
View File
@@ -25,13 +25,13 @@ function Layout() {
const { setModal, setPosition } = useModalStore();
return (
<div className="flex gap-[1.667vw] overflow-hidden">
<div className="flex gap-[1.667vw] overflow-hidden px-[2.222vw] pt-[1.667vw] pb-[2.778vw]">
<div className="flex-1"></div>
<div className="w-[42.5vw] flex flex-col gap-[1.667vw]">
<Navbar />
<Outlet />
</div>
<div className="flex-1 flex flex-col items-center gap-y-[0.833vw] py-[1.667vw]">
<div className="flex-1 flex flex-col items-center gap-y-[0.833vw]">
<AnimatePresence>
{currentStartedSessions?.map((session, index, { length }) => (
<CurrentSessionCard
+78 -60
View File
@@ -1,82 +1,100 @@
import { NavLink } from "react-router";
import clsx from "clsx";
import { Link, useLocation } from "react-router";
import HomeIcon from "./icons/HomeIcon";
import DesktopIcon from "./icons/DesktopIcon";
import NewButton from "./NewButton";
import clsx from "clsx";
import PeopleIcon from "./icons/PeopleIcon";
import ClientIcon from "./icons/ClientIcon";
import AppsIcon from "./icons/AppsIcon";
function Navbar() {
const { pathname } = useLocation();
return (
<div className="flex 2xl:gap-[0.278vw] items-center">
<NavLink
to="/"
className={({ isActive }) =>
clsx(
"2xl:p-[1.493vw] 2xl:py-[1.111vw] px-[21.5px] py-4 transition-colors flex 2xl:gap-[0.556vw] gap-2 items-center text-[#7D7D7D] hover:text-[#7B60F3]",
isActive && "text-[#7B60F3]"
)
}
<Link to="/">
<NewButton
variant="menu"
size="large"
className={clsx(
"pointer-events-none",
pathname === "/" && "!bg-[#F8F7FE] !text-[#7B60F3]"
)}
>
<span className="2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
<span className="2xl:size-[1.111vw] size-4">
<HomeIcon />
</span>
<span className="2xl:text-[0.972vw] text-sm font-medium">Главная</span>
</NavLink>
<NavLink
to="sessions"
className={({ isActive }) =>
clsx(
"2xl:p-[1.493vw] 2xl:py-[1.111vw] px-[21.5px] py-4 transition-colors flex 2xl:gap-[0.556vw] gap-2 items-center text-[#7D7D7D] hover:text-[#7B60F3]",
isActive && "text-[#7B60F3]"
)
}
<span className="2xl:text-[0.972vw] text-sm font-medium">
Главная
</span>
</NewButton>
</Link>
<Link to="/sessions">
<NewButton
variant="menu"
size="large"
className={clsx(
"pointer-events-none",
pathname === "/sessions" && "!bg-[#F8F7FE] !text-[#7B60F3]"
)}
>
<span className="2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
<span className="2xl:size-[1.111vw] size-4">
<DesktopIcon />
</span>
<span className="2xl:text-[0.972vw] text-sm font-medium">Сеансы</span>
</NavLink>
<NavLink
to="/"
className={({ isActive }) =>
clsx(
"2xl:p-[1.493vw] 2xl:py-[1.111vw] px-[21.5px] py-4 transition-colors flex 2xl:gap-[0.556vw] gap-2 items-center text-[#7D7D7D] hover:text-[#7B60F3]",
isActive && "text-[#7B60F3]"
)
}
</NewButton>
</Link>
<Link to="/">
<NewButton
variant="menu"
size="large"
className={clsx(
"pointer-events-none",
pathname === "/clients" && "!bg-[#F8F7FE] !text-[#7B60F3]"
)}
>
<span className="2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
<HomeIcon />
<span className="2xl:size-[1.111vw] size-4">
<PeopleIcon />
</span>
<span className="2xl:text-[0.972vw] text-sm font-medium">Главная</span>
</NavLink>
<NavLink
to="/"
className={({ isActive }) =>
clsx(
"2xl:p-[1.493vw] 2xl:py-[1.111vw] px-[21.5px] py-4 transition-colors flex 2xl:gap-[0.556vw] gap-2 items-center text-[#7D7D7D] hover:text-[#7B60F3]",
isActive && "text-[#7B60F3]"
)
}
<span className="2xl:text-[0.972vw] text-sm font-medium">
Менеджеры
</span>
</NewButton>
</Link>
<Link to="/">
<NewButton
variant="menu"
size="large"
className={clsx(
"pointer-events-none",
pathname === "/settings" && "!bg-[#F8F7FE] !text-[#7B60F3]"
)}
>
<span className="2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
<HomeIcon />
<span className="2xl:size-[1.111vw] size-4">
<ClientIcon />
</span>
<span className="2xl:text-[0.972vw] text-sm font-medium">Главная</span>
</NavLink>
<NavLink
to="/"
className={({ isActive }) =>
clsx(
"2xl:p-[1.493vw] 2xl:py-[1.111vw] px-[21.5px] py-4 transition-colors flex 2xl:gap-[0.556vw] gap-2 items-center text-[#7D7D7D] hover:text-[#7B60F3]",
isActive && "text-[#7B60F3]"
)
}
<span className="2xl:text-[0.972vw] text-sm font-medium">
Клиенты
</span>
</NewButton>
</Link>
<Link to="/">
<NewButton
variant="menu"
size="large"
className={clsx(
"pointer-events-none",
pathname === "/projects" && "!bg-[#F8F7FE] !text-[#7B60F3]"
)}
>
<span className="2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
<HomeIcon />
<span className="2xl:size-[1.111vw] size-4">
<AppsIcon />
</span>
<span className="2xl:text-[0.972vw] text-sm font-medium">Главная</span>
</NavLink>
{/* */}
<span className="2xl:text-[0.972vw] text-sm font-medium">
Проекты
</span>
</NewButton>
</Link>
</div>
);
}
+9 -4
View File
@@ -27,7 +27,7 @@ function NewButton({
onClick?.(e);
}}
className={clsx(
"transition-all 2xl:rounded-[0.556vw] rounded-lg flex 2xl:gap-[0.556vw] gap-2 items-center justify-center font-medium disabled:bg-[#F6F6F6] disabled:text-[#D6D6D6]",
"transition-all flex 2xl:gap-[0.556vw] gap-2 items-center justify-center font-medium disabled:bg-[#F6F6F6] disabled:text-[#D6D6D6]",
variant === "critical" &&
"text-[#FF4517] bg-[#FEF3F2] hover:bg-[#FEE4E2]",
variant === "secondary" &&
@@ -36,9 +36,14 @@ function NewButton({
"bg-[#F8F7FE] text-[#7B60F3] hover:bg-[#E1DEFC] active:bg-[#F8F7FE]",
variant === "cta" &&
"bg-[#7B60F3] text-white hover:bg-[#9184F6] active:bg-[#B3AAF9]",
size === "large" && "2xl:p-[1.111vw] p-4 button-m",
size === "medium" && "2xl:p-[0.833vw] p-3 button-s",
size === "small" && "2xl:p-[0.556vw] p-2 text-[10px]",
variant === "menu" &&
"text-[#7D7D7D] hover:bg-[#F0F0F0] active:bg-[#F8F7FE] active:text-[#7B60F3] disabled:text-[#D6D6D6] disabled:bg-[#F6F6F6]",
size === "large" &&
"2xl:p-[1.111vw] p-4 button-m 2xl:rounded-[0.833vw] rounded-xl",
size === "medium" &&
"2xl:p-[0.833vw] p-3 button-s 2xl:rounded-[0.833vw] rounded-xl",
size === "small" &&
"2xl:p-[0.556vw] p-2 text-[10px] 2xl:rounded-[0.556vw] rounded-lg",
className
)}
>
+1 -1
View File
@@ -6,7 +6,7 @@ function SessionCard({ session }: { session: Session }) {
const { setModal, setPosition } = useModalStore();
return (
<div
className="w-full h-[4.444vw] border-b-1 first:border-t-1 border-[#F6F6F6] flex py-[0.278vw] items-center gap-[0.556vw] cursor-pointer group"
className="w-full h-[4.444vw] not-last:border-b-1 border-[#F6F6F6] flex py-[0.278vw] items-center gap-[0.556vw] cursor-pointer group"
onClick={() => {
setModal(<SessionModal session={session} />);
setPosition("right");
+28
View File
@@ -0,0 +1,28 @@
function AppsIcon() {
return (
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="a" fill="#fff">
<rect width={8.58} height={8.58} rx={1} />
</mask>
<rect
width={8.58}
height={8.58}
rx={1}
transform="matrix(.87416 .48564 -.87416 .48564 10 3.5)"
stroke="currentColor"
strokeWidth={2.4}
mask="url(#a)"
/>
<path
d="M10.875 14.894c-.483.268-1.266.268-1.749 0l-5.828-3.238c-.449-.25-.473-.65-.055-.914.23-.146.633-.154.88-.017l5.368 2.983a1 1 0 0 0 .868.003l5.48-2.964a.96.96 0 0 1 .828.003c.46.256.46.67 0 .926l-5 2.778z"
fill="currentColor"
/>
<path
d="M10.874 18.014c-.483.268-1.265.268-1.748 0l-5.91-3.283c-.416-.231-.48-.594-.154-.866l.026-.022c.215-.179.668-.206.945-.056l5.537 2.981c.24.13.62.13.86 0l5.537-2.981c.277-.15.73-.123.945.056l.026.022c.327.272.262.635-.155.866l-5.116 2.843z"
fill="currentColor"
/>
</svg>
);
}
export default AppsIcon;
+22
View File
@@ -0,0 +1,22 @@
function ClientIcon() {
return (
<svg viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M3.45 12.28v1.32h9.6v-12h-9.6v1.68M2.25 9.6h1.333m-1.333-2h1.333m-1.333-2h1.333"
stroke="currentColor"
strokeWidth={1.2}
strokeLinecap="square"
strokeLinejoin="round"
/>
<path
d="M8.25 7a1.333 1.333 0 1 0 0-2.667A1.333 1.333 0 0 0 8.25 7Zm2.666 4.667a2.667 2.667 0 1 0-5.333 0"
stroke="currentColor"
strokeWidth={1.2}
strokeLinecap="square"
strokeLinejoin="round"
/>
</svg>
);
}
export default ClientIcon;
+6
View File
@@ -41,9 +41,11 @@ function EditTable({ table }: { table: Server }) {
isError={tableName.length > 16}
errorMessage="Не больше 16 символов"
/>
{tableName.length <= 16 && (
<p className="caption-s text-[#BDBDBD] font-medium w-full tracking-[-0.02em]">
Придумайте название до 16 символов, например «Тузик»
</p>
)}
</div>
<div className="space-y-[0.556vw]">
<NewInput
@@ -53,13 +55,16 @@ function EditTable({ table }: { table: Server }) {
isError={tableDescription.length > 20}
errorMessage="Не больше 20 символов"
/>
{tableDescription.length <= 20 && (
<p className="caption-s text-[#BDBDBD] font-medium w-full tracking-[-0.02em]">
Придумайте описание до 20 символов, например «Расположен в офисе»
</p>
)}
</div>
<div className="flex flex-col gap-[0.556vw]">
<NewButton
variant="cta"
size="large"
disabled={
tableName.length < 1 ||
tableName.length > 16 ||
@@ -72,6 +77,7 @@ function EditTable({ table }: { table: Server }) {
</NewButton>
<NewButton
variant="primary"
size="large"
className="flex justify-center"
onClick={() => setModal(null)}
>
+1 -1
View File
@@ -14,7 +14,7 @@ import SessionComments from "../SessionComments";
function SessionModal({ session }: { session: Session }) {
return (
<div className="bg-[#FFFFFF] w-[49.722vw] rounded-[2.222vw]">
<div className="w-full flex justify-center items-center h-[4.861vw]">
<div className="w-full flex justify-center items-center h-[4.861vw] border-b-1 border-[#D6D6D6]">
<div className="title-s flex font-medium">
<p>{format(session.createdAt, "dd MMMM yyyy", { locale: ru })}</p>
<p>,&nbsp;{format(session.createdAt, "HH:mm")}</p>