diff --git a/src/assets/fonts/iransans/IRANSans(FaNum).ttf b/src/assets/fonts/iransans/IRANSans(FaNum).ttf new file mode 100644 index 0000000..b703642 Binary files /dev/null and b/src/assets/fonts/iransans/IRANSans(FaNum).ttf differ diff --git a/src/assets/fonts/iransans/IRANSans(FaNum)_Bold.ttf b/src/assets/fonts/iransans/IRANSans(FaNum)_Bold.ttf new file mode 100644 index 0000000..640b340 Binary files /dev/null and b/src/assets/fonts/iransans/IRANSans(FaNum)_Bold.ttf differ diff --git a/src/assets/fonts/iransans/IRANSans(FaNum)_Light.ttf b/src/assets/fonts/iransans/IRANSans(FaNum)_Light.ttf new file mode 100644 index 0000000..44e4c8a Binary files /dev/null and b/src/assets/fonts/iransans/IRANSans(FaNum)_Light.ttf differ diff --git a/src/assets/fonts/iransans/IRANSans(FaNum)_Medium.ttf b/src/assets/fonts/iransans/IRANSans(FaNum)_Medium.ttf new file mode 100644 index 0000000..0c34cda Binary files /dev/null and b/src/assets/fonts/iransans/IRANSans(FaNum)_Medium.ttf differ diff --git a/src/assets/fonts/iransans/IRANSans(FaNum)_UltraLight.ttf b/src/assets/fonts/iransans/IRANSans(FaNum)_UltraLight.ttf new file mode 100644 index 0000000..d3ebe15 Binary files /dev/null and b/src/assets/fonts/iransans/IRANSans(FaNum)_UltraLight.ttf differ diff --git a/src/assets/fonts/iransans/IRANSans.ttf b/src/assets/fonts/iransans/IRANSans.ttf new file mode 100644 index 0000000..320211c Binary files /dev/null and b/src/assets/fonts/iransans/IRANSans.ttf differ diff --git a/src/assets/fonts/iransans/IRANSansX-Bold.ttf b/src/assets/fonts/iransans/IRANSansX-Bold.ttf new file mode 100644 index 0000000..1d57a9a Binary files /dev/null and b/src/assets/fonts/iransans/IRANSansX-Bold.ttf differ diff --git a/src/assets/fonts/iransans/IRANSansX-Regular.ttf b/src/assets/fonts/iransans/IRANSansX-Regular.ttf new file mode 100644 index 0000000..69cf084 Binary files /dev/null and b/src/assets/fonts/iransans/IRANSansX-Regular.ttf differ diff --git a/src/assets/fonts/iransans/IRANSansXFaNum-Bold.ttf b/src/assets/fonts/iransans/IRANSansXFaNum-Bold.ttf new file mode 100644 index 0000000..0bea395 Binary files /dev/null and b/src/assets/fonts/iransans/IRANSansXFaNum-Bold.ttf differ diff --git a/src/assets/fonts/iransans/IRANSansXFaNum-Regular.ttf b/src/assets/fonts/iransans/IRANSansXFaNum-Regular.ttf new file mode 100644 index 0000000..86f5b80 Binary files /dev/null and b/src/assets/fonts/iransans/IRANSansXFaNum-Regular.ttf differ diff --git a/src/assets/fonts/iransans/IRANSansXNoEn-Bold.ttf b/src/assets/fonts/iransans/IRANSansXNoEn-Bold.ttf new file mode 100644 index 0000000..088872c Binary files /dev/null and b/src/assets/fonts/iransans/IRANSansXNoEn-Bold.ttf differ diff --git a/src/assets/fonts/iransans/IRANSansXNoEn-Regular.ttf b/src/assets/fonts/iransans/IRANSansXNoEn-Regular.ttf new file mode 100644 index 0000000..aff9823 Binary files /dev/null and b/src/assets/fonts/iransans/IRANSansXNoEn-Regular.ttf differ diff --git a/src/assets/fonts/iransans/IRANSans_Black.ttf b/src/assets/fonts/iransans/IRANSans_Black.ttf new file mode 100644 index 0000000..5fb4340 Binary files /dev/null and b/src/assets/fonts/iransans/IRANSans_Black.ttf differ diff --git a/src/assets/fonts/iransans/IRANSans_Bold.ttf b/src/assets/fonts/iransans/IRANSans_Bold.ttf new file mode 100644 index 0000000..dfa64eb Binary files /dev/null and b/src/assets/fonts/iransans/IRANSans_Bold.ttf differ diff --git a/src/assets/fonts/iransans/IRANSans_Light.ttf b/src/assets/fonts/iransans/IRANSans_Light.ttf new file mode 100644 index 0000000..f91be8e Binary files /dev/null and b/src/assets/fonts/iransans/IRANSans_Light.ttf differ diff --git a/src/assets/fonts/iransans/IRANSans_Medium.ttf b/src/assets/fonts/iransans/IRANSans_Medium.ttf new file mode 100644 index 0000000..403019f Binary files /dev/null and b/src/assets/fonts/iransans/IRANSans_Medium.ttf differ diff --git a/src/assets/fonts/iransans/IRANSans_UltraLight.ttf b/src/assets/fonts/iransans/IRANSans_UltraLight.ttf new file mode 100644 index 0000000..8f06c90 Binary files /dev/null and b/src/assets/fonts/iransans/IRANSans_UltraLight.ttf differ diff --git a/src/assets/hero.png b/src/assets/hero.png deleted file mode 100644 index 02251f4..0000000 Binary files a/src/assets/hero.png and /dev/null differ diff --git a/src/assets/images/winsoo.svg b/src/assets/images/winsoo.svg new file mode 100644 index 0000000..cf488d1 --- /dev/null +++ b/src/assets/images/winsoo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/react.svg b/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/vite.svg b/src/assets/vite.svg deleted file mode 100644 index 5101b67..0000000 --- a/src/assets/vite.svg +++ /dev/null @@ -1 +0,0 @@ -Vite diff --git a/src/components/layout/AdminLayout.tsx b/src/components/layout/AdminLayout.tsx index 7209d76..849b89a 100644 --- a/src/components/layout/AdminLayout.tsx +++ b/src/components/layout/AdminLayout.tsx @@ -1,8 +1,9 @@ -import { Layout, Menu, Typography, theme } from 'antd'; -import { Home, UserRound, MonitorPlay } from 'lucide'; -import type { ReactNode } from 'react'; -import { useNavigate, useLocation } from 'react-router-dom'; -import LucideIcon from '../ui/LucideIcon'; +import { Drawer, Layout, Menu, Typography, theme } from "antd"; +import { useEffect, useState } from "react"; +import type { ReactNode } from "react"; +import { useNavigate, useLocation } from "react-router-dom"; +import winsooLogo from "../../assets/images/winsoo.svg"; +import { getSidebarMenuItems } from "../../constants/navigation"; const { Header, Content, Sider } = Layout; const { Title } = Typography; @@ -15,56 +16,123 @@ const AdminLayout = ({ children }: AdminLayoutProps) => { const navigate = useNavigate(); const location = useLocation(); const { - token: { colorBgContainer, borderRadiusLG }, + token: { borderRadiusLG }, } = theme.useToken(); + const [mobileOpen, setMobileOpen] = useState(false); + const [isMobile, setIsMobile] = useState(false); - const items = [ - { - key: '/profile', - icon: , - label: 'پروفایل کاربر', - }, - { - key: '/billboards', - icon: , - label: 'بیلبوردها', - }, - { - key: '/future', - icon: , - label: 'بخش‌های آینده', - }, - ]; + const items = getSidebarMenuItems(); + + useEffect(() => { + const handleResize = () => { + setIsMobile(window.innerWidth < 992); + }; + + handleResize(); + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + + const handleNavigate = (key: string) => { + navigate(key); + if (isMobile) { + setMobileOpen(false); + } + }; + + const sidebarContent = ( + <> +
+ Winsoo Logo +
+ handleNavigate(String(key))} + style={{ + borderInlineEnd: 0, + paddingTop: 12, + background: "#ffffff", + color: "#000000", + }} + theme="light" + className="sidebar-menu" + /> + + ); return ( - - -
- - Winsoo - -
- navigate(key)} - style={{ borderInlineEnd: 0, paddingTop: 12 }} - /> - + + {isMobile ? ( + setMobileOpen(false)} + width={260} + bodyStyle={{ padding: 0, background: "#ffffff" }} + closeIcon={null} + > + {sidebarContent} + + ) : ( + + {sidebarContent} + + )}
- + {isMobile ? ( + <div + style={{ + width: 40, + height: 40, + borderRadius: 8, + background: "rgba(255,255,255,0.15)", + display: "flex", + alignItems: "center", + justifyContent: "center", + cursor: "pointer", + color: "#ffffff", + }} + onClick={() => setMobileOpen(true)} + role="button" + tabIndex={0} + onKeyDown={(event) => { + if (event.key === "Enter" || event.key === " ") { + setMobileOpen(true); + } + }} + > + ☰ + </div> + ) : null} + <Title level={4} style={{ margin: 0, color: "#ffffff", flex: 1, textAlign: "center" }}> پنل ادمین وینسو
@@ -72,10 +140,11 @@ const AdminLayout = ({ children }: AdminLayoutProps) => {
{children} diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 536bd89..9e7838a 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -1,37 +1,18 @@ import { Menu } from 'antd'; -import { Home, MonitorPlay, UserRound } from 'lucide'; import { useNavigate, useLocation } from 'react-router-dom'; -import LucideIcon from '../ui/LucideIcon'; +import { getSidebarMenuItems } from '../../constants/navigation'; const Sidebar = () => { const navigate = useNavigate(); const location = useLocation(); - const items = [ - { - key: '/profile', - icon: , - label: 'پروفایل کاربر', - }, - { - key: '/billboards', - icon: , - label: 'بیلبوردها', - }, - { - key: '/', - icon: , - label: 'داشبورد', - }, - ]; - return ( navigate(key)} - style={{ height: '100%', borderInlineEnd: 0, paddingTop: 12 }} + style={{ height: '100%', borderInlineEnd: 0, paddingTop: 12, background: '#ffffff', color: '#000000' }} /> ); }; diff --git a/src/constants/navigation.tsx b/src/constants/navigation.tsx new file mode 100644 index 0000000..1f7473a --- /dev/null +++ b/src/constants/navigation.tsx @@ -0,0 +1,37 @@ +import { Home, MonitorPlay, UserRound } from 'lucide'; +import type { ReactNode } from 'react'; +import type { MenuProps } from 'antd'; +import LucideIcon from '../components/ui/LucideIcon'; + +export type SidebarItemKey = '/profile' | '/billboards' | '/'; + +export interface SidebarItem { + key: SidebarItemKey; + label: string; + icon: ReactNode; +} + +export const sidebarItems: SidebarItem[] = [ + { + key: '/profile', + label: 'پروفایل کاربر', + icon: , + }, + { + key: '/billboards', + label: 'بیلبوردها', + icon: , + }, + { + key: '/', + label: 'داشبورد', + icon: , + }, +]; + +export const getSidebarMenuItems = (): NonNullable => + sidebarItems.map((item) => ({ + key: item.key, + label: {item.icon}{item.label}, + icon: {item.icon}, + })); diff --git a/src/index.css b/src/index.css index 3536c3c..70b00b4 100644 --- a/src/index.css +++ b/src/index.css @@ -1,11 +1,31 @@ -@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;500;700&display=swap'); +@font-face { + font-family: 'IRANSans'; + src: url('./assets/fonts/iransans/IRANSans.ttf') format('truetype'); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'IRANSans'; + src: url('./assets/fonts/iransans/IRANSans_Bold.ttf') format('truetype'); + font-weight: 700; + font-style: normal; + font-display: swap; +} :root { - font-family: 'Vazirmatn', sans-serif; + font-family: 'IRANSans', sans-serif; line-height: 1.5; font-weight: 400; - color: #111827; - background: #f8fafc; + color: #000000; + background: #ffffff; + --primary-blue: #233E5F; + --soft-blue: #ECF2F8; + --accent-orange: #F0642D; + --text-main: #000000; + --text-subtle: #B3B3B3; + --surface-white: #ffffff; font-synthesis: none; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; @@ -20,7 +40,8 @@ body { margin: 0; min-width: 320px; min-height: 100vh; - background: linear-gradient(135deg, #f8fafc 0%, #eef2ff 100%); + background: var(--surface-white); + color: var(--text-main); } #root { @@ -35,3 +56,34 @@ h4, p { margin: 0; } + +.sidebar-menu { + padding: 8px 4px; +} + +.sidebar-menu .ant-menu-item { + border-radius: 10px; + padding-inline: 16px !important; + padding-block: 10px !important; + color: #000000; + display: flex; + align-items: center; +} + +.sidebar-menu .ant-menu-item .ant-menu-title-content { + display: flex; + align-items: center; + width: fit-content; +} + +.sidebar-menu .ant-menu-item:hover, +.sidebar-menu .ant-menu-item-active, +.sidebar-menu .ant-menu-item-selected { + background-color: #ECF2F8 !important; + color: #233E5F !important; +} + +.sidebar-menu .ant-menu-item-selected .ant-menu-title-content, +.sidebar-menu .ant-menu-item:hover .ant-menu-title-content { + color: #233E5F !important; +} diff --git a/src/main.tsx b/src/main.tsx index 1c7fa66..2f453d3 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -17,9 +17,13 @@ createRoot(document.getElementById('root')!).render( locale={faIR} theme={{ token: { - colorPrimary: '#4f46e5', + colorPrimary: '#233E5F', + colorInfo: '#233E5F', + colorSuccess: '#233E5F', borderRadius: 12, - fontFamily: 'Vazirmatn, sans-serif', + fontFamily: 'IRANSans, sans-serif', + colorText: '#000000', + colorTextSecondary: '#B3B3B3', }, }} > diff --git a/src/pages/Billboards/Billboards.tsx b/src/pages/Billboards/Billboards.tsx index 4eb8a28..9c03a26 100644 --- a/src/pages/Billboards/Billboards.tsx +++ b/src/pages/Billboards/Billboards.tsx @@ -1,13 +1,15 @@ -import { Typography } from 'antd'; +import { Card, Typography } from 'antd'; const { Title, Paragraph } = Typography; const Billboards = () => { return ( -
+ بیلبوردها - مدیریت جدول بیلبوردها به‌زودی اضافه خواهد شد. -
+ + مدیریت جدول بیلبوردها به‌زودی اضافه خواهد شد. + + ); }; diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx index 3d7c952..a6efb1a 100644 --- a/src/pages/Home/Home.tsx +++ b/src/pages/Home/Home.tsx @@ -1,15 +1,15 @@ -import { Typography } from 'antd'; +import { Card, Typography } from 'antd'; const { Title, Paragraph } = Typography; const Home = () => { return ( -
+ خوش آمدید - + به پنل ادمین وینسو خوش آمدید. -
+ ); }; diff --git a/src/pages/Login/Login.tsx b/src/pages/Login/Login.tsx index 008b356..6b93419 100644 --- a/src/pages/Login/Login.tsx +++ b/src/pages/Login/Login.tsx @@ -24,12 +24,12 @@ const Login = () => { }; return ( -
- - + <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#ECF2F8', direction: 'rtl' }}> + <Card style={{ width: 420, boxShadow: '0 12px 32px rgba(35, 62, 95, 0.12)', border: '1px solid #ECF2F8' }}> + <Title level={3} style={{ marginBottom: 8, color: '#233E5F' }}> ورود به پنل ادمین - + برای ادامه شماره موبایل خود را وارد کنید. diff --git a/src/pages/Profile/Profile.tsx b/src/pages/Profile/Profile.tsx index 68e6d7a..cae582c 100644 --- a/src/pages/Profile/Profile.tsx +++ b/src/pages/Profile/Profile.tsx @@ -1,13 +1,15 @@ -import { Typography } from 'antd'; +import { Card, Typography } from 'antd'; const { Title, Paragraph } = Typography; const Profile = () => { return ( -
+ پروفایل کاربر - جدول اطلاعات کاربر به‌زودی اضافه خواهد شد. -
+ + جدول اطلاعات کاربر به‌زودی اضافه خواهد شد. + +
); }; diff --git a/src/pages/VerifyOtp/VerifyOtp.tsx b/src/pages/VerifyOtp/VerifyOtp.tsx index 8f77698..e498c08 100644 --- a/src/pages/VerifyOtp/VerifyOtp.tsx +++ b/src/pages/VerifyOtp/VerifyOtp.tsx @@ -37,12 +37,12 @@ const VerifyOtp = () => { }; return ( -
- - + <div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#ECF2F8', direction: 'rtl' }}> + <Card style={{ width: 420, boxShadow: '0 12px 32px rgba(35, 62, 95, 0.12)', border: '1px solid #ECF2F8' }}> + <Title level={3} style={{ marginBottom: 8, color: '#233E5F' }}> تایید کد یکبار مصرف - + کد تایید: 77501