refactor layout
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-07-17 19:02:39 +03:30
parent d85e0e49ce
commit dcb2c1326c
5 changed files with 122 additions and 78 deletions
+26
View File
@@ -48,6 +48,32 @@ textarea::placeholder {
--color-desc: #8c90a3;
}
:root {
/* App shell — keep Header / Sidebar / AppLayout in sync */
--layout-frame: 1rem;
--layout-sidebar-width: 240px;
/* Sidebar width + frame gap (was 269px ≈ 29px gutter — felt too wide) */
--layout-main-offset: calc(var(--layout-sidebar-width) + var(--layout-frame));
--layout-header-height: 3rem;
--layout-header-height-xl: 4rem;
--layout-header-stack: calc(var(--layout-header-height) + 0.75rem);
--layout-header-stack-xl: calc(var(--layout-header-height-xl) + 1rem);
--layout-content-pad-x: 1rem;
}
.app-main {
scrollbar-gutter: stable;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.no-scrollbar::-webkit-scrollbar {
display: none;
}
tbody tr:nth-child(odd) {
background-color: #f5f7fc;
}
+61 -73
View File
@@ -1,8 +1,7 @@
import { type FC } from "react";
import { Route, Routes, useLocation } from "react-router-dom";
import Home from "../pages/home/Home";
import SideBar from "../shared/Sidebar";
import Header from "../shared/Header";
import AppLayout from "../shared/AppLayout";
import { Paths } from "@/config/Paths";
import ProformaInvoice from "@/pages/invoice/ProformaInvoice";
import CreateInvoice from "@/pages/invoice/Create";
@@ -72,88 +71,77 @@ const MainRouter: FC = () => {
}
return (
<div className="p-4 overflow-hidden">
<Header />
<SideBar />
<div className="flex-1 xl:ms-[269px] mt-[68px] xl:mt-[81px]">
<div
className={`overflow-auto w-[${window.innerWidth}] max-h-[calc(100vh-113px)]`}
>
<div className="xl:pb-20 pb-32">
<Routes>
<Route path="/" element={<Home />} />
<Route path={Paths.home} element={<Home />} />
<Route path={Paths.perfomaInvoice.list} element={<ProformaInvoice />} />
<Route path={Paths.payments.list} element={<PaymentsList />} />
<Route path={Paths.perfomaInvoice.create} element={<CreateInvoice />} />
<Route path={Paths.perfomaInvoice.detail + ":id"} element={<DetailPerfomaInvoice />} />
<Route path={Paths.perfomaInvoice.update + ":id"} element={<UpdateInvoice />} />
<Route path={Paths.requests.list} element={<RequestList />} />
<Route path={Paths.requests.detail + ":id"} element={<RequestDetail />} />
<Route path={Paths.product.list} element={<ProductList />} />
<Route path={Paths.product.create} element={<CreateProduct />} />
<Route path={Paths.product.update + ":id"} element={<UpdateProduct />} />
<Route path={Paths.product.attribute.create + ":id"} element={<CreateAttribute />} />
<Route path={Paths.product.attribute.list + ":id"} element={<AttributeList />} />
<Route path={Paths.product.attribute.update + ":id"} element={<UpdateAttribute />} />
<Route path={Paths.product.attributeValue.list + ":id"} element={<AttributeValues />} />
<Route path={Paths.product.category.list} element={<CategoryList />} />
<Route path={Paths.product.category.create} element={<CreateCategory />} />
<Route path={Paths.product.category.update + ":id"} element={<UpdateCategory />} />
<AppLayout>
<Routes>
<Route path="/" element={<Home />} />
<Route path={Paths.home} element={<Home />} />
<Route path={Paths.perfomaInvoice.list} element={<ProformaInvoice />} />
<Route path={Paths.payments.list} element={<PaymentsList />} />
<Route path={Paths.perfomaInvoice.create} element={<CreateInvoice />} />
<Route path={Paths.perfomaInvoice.detail + ":id"} element={<DetailPerfomaInvoice />} />
<Route path={Paths.perfomaInvoice.update + ":id"} element={<UpdateInvoice />} />
<Route path={Paths.requests.list} element={<RequestList />} />
<Route path={Paths.requests.detail + ":id"} element={<RequestDetail />} />
<Route path={Paths.product.list} element={<ProductList />} />
<Route path={Paths.product.create} element={<CreateProduct />} />
<Route path={Paths.product.update + ":id"} element={<UpdateProduct />} />
<Route path={Paths.product.attribute.create + ":id"} element={<CreateAttribute />} />
<Route path={Paths.product.attribute.list + ":id"} element={<AttributeList />} />
<Route path={Paths.product.attribute.update + ":id"} element={<UpdateAttribute />} />
<Route path={Paths.product.attributeValue.list + ":id"} element={<AttributeValues />} />
<Route path={Paths.product.category.list} element={<CategoryList />} />
<Route path={Paths.product.category.create} element={<CreateCategory />} />
<Route path={Paths.product.category.update + ":id"} element={<UpdateCategory />} />
<Route path={Paths.formBuilder.list + ":id/:type"} element={<FormBuilderList />} />
<Route path={Paths.formBuilder.create + ":id/:type"} element={<FormBuilderCreate />} />
<Route path={Paths.formBuilder.update + ":id"} element={<FormBuilderUpdate />} />
<Route path={Paths.formBuilder.values + ":id"} element={<FormBuilderValues />} />
<Route path={Paths.formBuilder.list + ":id/:type"} element={<FormBuilderList />} />
<Route path={Paths.formBuilder.create + ":id/:type"} element={<FormBuilderCreate />} />
<Route path={Paths.formBuilder.update + ":id"} element={<FormBuilderUpdate />} />
<Route path={Paths.formBuilder.values + ":id"} element={<FormBuilderValues />} />
<Route path={Paths.order.list} element={<OrdersList />} />
<Route path={Paths.order.details + ":id"} element={<OrderDetail />} />
<Route path={Paths.order.create} element={<NewOrder />} />
<Route path={Paths.order.edit + ":id"} element={<EditOrder />} />
<Route path={Paths.convertToOrder} element={<ConvertToOrders />} />
<Route path={Paths.orderPrint + ':id/preview'} element={<OrderPrintPreview />} />
<Route path={Paths.orderPrint + ':id'} element={<OrderPrint />} />
<Route path={Paths.order.list} element={<OrdersList />} />
<Route path={Paths.order.details + ":id"} element={<OrderDetail />} />
<Route path={Paths.order.create} element={<NewOrder />} />
<Route path={Paths.order.edit + ":id"} element={<EditOrder />} />
<Route path={Paths.convertToOrder} element={<ConvertToOrders />} />
<Route path={Paths.orderPrint + ':id/preview'} element={<OrderPrintPreview />} />
<Route path={Paths.orderPrint + ':id'} element={<OrderPrint />} />
<Route path={Paths.tickets.list} element={<TicketList />} />
<Route path={Paths.tickets.detail + ":id"} element={<TicketDetail />} />
<Route path={Paths.tickets.list} element={<TicketList />} />
<Route path={Paths.tickets.detail + ":id"} element={<TicketDetail />} />
<Route path={Paths.print.list} element={<SectionList />} />
<Route path={Paths.print.create} element={<CreateSection />} />
<Route path={Paths.print.update + ":id"} element={<UpdateSection />} />
<Route path={Paths.print.form + ":itemId/:orderId"} element={<PrintForm />} />
<Route path={Paths.print.list} element={<SectionList />} />
<Route path={Paths.print.create} element={<CreateSection />} />
<Route path={Paths.print.update + ":id"} element={<UpdateSection />} />
<Route path={Paths.print.form + ":itemId/:orderId"} element={<PrintForm />} />
<Route path={Paths.users.list} element={<UsersList />} />
<Route path={Paths.users.create} element={<CreateUser />} />
<Route path={Paths.users.update + ":id"} element={<UpdateUser />} />
<Route path={Paths.users.list} element={<UsersList />} />
<Route path={Paths.users.create} element={<CreateUser />} />
<Route path={Paths.users.update + ":id"} element={<UpdateUser />} />
<Route path={Paths.admin.list} element={<AdminList />} />
<Route path={Paths.admin.create} element={<CreateAdmin />} />
<Route path={Paths.admin.update + ":id"} element={<EditAdmin />} />
<Route path={Paths.admin.list} element={<AdminList />} />
<Route path={Paths.admin.create} element={<CreateAdmin />} />
<Route path={Paths.admin.update + ":id"} element={<EditAdmin />} />
<Route path={Paths.role.list} element={<RoleList />} />
<Route path={Paths.role.create} element={<CreateRole />} />
<Route path={Paths.role.update + ":id"} element={<UpdateRole />} />
<Route path={Paths.role.list} element={<RoleList />} />
<Route path={Paths.role.create} element={<CreateRole />} />
<Route path={Paths.role.update + ":id"} element={<UpdateRole />} />
<Route path={Paths.features.list} element={<FeaturesList />} />
<Route path={Paths.features.create} element={<CreateFeature />} />
<Route path={Paths.service.print} element={<PrintService />} />
<Route path={Paths.features.list} element={<FeaturesList />} />
<Route path={Paths.features.create} element={<CreateFeature />} />
<Route path={Paths.service.print} element={<PrintService />} />
<Route path={Paths.announcement.list} element={<AnnouncementList />} />
<Route path={Paths.announcement.detail + ":id"} element={<AnnouncementUpdate />} />
<Route path={Paths.announcement.create} element={<AnnouncementCreate />} />
<Route path={Paths.announcement.list} element={<AnnouncementList />} />
<Route path={Paths.announcement.detail + ":id"} element={<AnnouncementUpdate />} />
<Route path={Paths.announcement.create} element={<AnnouncementCreate />} />
<Route path={Paths.criticisms.list} element={<CriticismsList />} />
<Route path={Paths.criticisms.detail + ":id"} element={<CriticismsDetail />} />
<Route path={Paths.criticisms.list} element={<CriticismsList />} />
<Route path={Paths.criticisms.detail + ":id"} element={<CriticismsDetail />} />
<Route path={Paths.learning.list} element={<LearningList />} />
<Route path={Paths.learning.create} element={<LearningCreate />} />
<Route path={Paths.learning.category} element={<LearningCategory />} />
</Routes>
</div>
</div>
</div>
</div>
<Route path={Paths.learning.list} element={<LearningList />} />
<Route path={Paths.learning.create} element={<LearningCreate />} />
<Route path={Paths.learning.category} element={<LearningCategory />} />
</Routes>
</AppLayout>
);
};
+30
View File
@@ -0,0 +1,30 @@
import { type FC, type ReactNode } from 'react'
import Header from './Header'
import SideBar from './Sidebar'
type AppLayoutProps = {
children: ReactNode
}
/**
* Authenticated app shell: fixed header + sidebar, one scrollable main column.
* Horizontal padding on the scrollport keeps content clear of the RTL scrollbar.
*/
const AppLayout: FC<AppLayoutProps> = ({ children }) => {
return (
<div className="box-border flex h-dvh flex-col overflow-hidden p-[var(--layout-frame)]">
<Header />
<SideBar />
<div className="flex min-h-0 flex-1 flex-col pt-[var(--layout-header-stack)] xl:ms-[var(--layout-main-offset)] xl:pt-[var(--layout-header-stack-xl)]">
<main className="app-main min-h-0 flex-1 overflow-y-auto overscroll-contain">
<div className="min-w-0 px-[var(--layout-content-pad-x)] pb-28 xl:pb-16">
{children}
</div>
</main>
</div>
</div>
)
}
export default AppLayout
+1 -1
View File
@@ -28,7 +28,7 @@ const Header: FC = () => {
}, [location.pathname]);
return (
<div className='fixed z-10 right-4 left-4 xl:right-[285px] top-4 xl:h-16 h-12 flex items-center px-6 bg-white justify-between rounded-[32px] xl:w-[calc(100%-305px)]'>
<div className='fixed z-10 left-[var(--layout-frame)] right-[var(--layout-frame)] top-[var(--layout-frame)] flex h-[var(--layout-header-height)] items-center justify-between rounded-[32px] bg-white px-6 xl:left-auto xl:right-[calc(var(--layout-frame)+var(--layout-main-offset))] xl:h-[var(--layout-header-height-xl)] xl:w-[calc(100%-(var(--layout-frame)*2)-var(--layout-main-offset))]'>
<div className='min-w-[270px] hidden xl:block'>
<Input
+4 -4
View File
@@ -48,17 +48,17 @@ const SideBar: FC = () => {
)}
<div
className={clx(
'fixed xl:flex translate-x-[400px] xl:translate-x-0 transition-all ease-in-out opacity-0 invisible xl:visible xl:opacity-100 xl:right-4 right-0 xl:top-4 top-0 xl:bottom-4 bottom-0 xl:rounded-[32px] w-[240px] bg-white flex-col py-12',
openSidebar && 'opacity-100 visible -translate-x-[0px] block z-40'
'fixed right-0 top-0 bottom-0 flex w-[var(--layout-sidebar-width)] translate-x-[400px] flex-col overflow-hidden bg-white py-12 opacity-0 invisible transition-all ease-in-out xl:right-[var(--layout-frame)] xl:top-[var(--layout-frame)] xl:bottom-[var(--layout-frame)] xl:z-40 xl:translate-x-0 xl:rounded-[32px] xl:opacity-100 xl:visible',
openSidebar && 'visible z-40 flex translate-x-0 opacity-100'
)}
>
<div className="px-6">
<div className="shrink-0 px-6">
<div className="flex border-b-2 border-[#F5F7FC] pb-10">
<img src={LogoImage} className="w-[120px]" />
</div>
</div>
<div className="flex-1 h-full overflow-y-auto no-scrollbar px-6">
<div className="min-h-0 flex-1 overflow-y-auto no-scrollbar px-6">
<div className="mt-10 text-description px-6 text-header text-sm font-bold">{t('sidebar.menu')}</div>
<div className="mt-3">