color palette

This commit is contained in:
Mahdi Rahimi 2025-12-25 13:58:06 +03:30
parent 5070f36c8e
commit da80b5d444
8 changed files with 254 additions and 127 deletions

View File

@ -1,6 +1,17 @@
import AppRoutes from "./routes/routes";
import { useEffect } from "react";
function App() {
const checkTheme = () => {
if (localStorage.theme ? (localStorage.theme === "dark") : (window.matchMedia("(prefers-color-scheme: dark)").matches)) {
document.documentElement.classList.add("dark");
}
};
useEffect(() => {
checkTheme();
}, []);
return (
<AppRoutes />
);

View File

@ -0,0 +1,11 @@
export default function toggleTheme() {
const html = document.documentElement;
if (html.classList.contains("dark")) {
html.classList.remove("dark");
localStorage.theme = "light";
} else {
html.classList.add("dark");
localStorage.theme = "dark";
}
}

View File

@ -29,26 +29,34 @@ import Search from "../../../assets/icons/search.svg";
import Arrow from "../../../assets/icons/arrow.svg";
import Vector7 from "../../../assets/icons/Vector7.svg";
import Pic from "../../../assets/icons/pic.png";
import toggleTheme from "../../ToggleTheme";
const Header = ({ title }) => {
return (
<header className="flex items-center justify-end gap-4 p-3 ml-5 mr-2">
<header className="flex bg-header items-center justify-end gap-4 p-3 ml-5 mr-2">
{/* <h3 className="text-[#402E32] font-bold text-lg">{title}</h3> */}
<div className="flex items-center gap-2">
<div className="w-12 h-10 border-2 border-[#8B8886] flex justify-center items-center rounded-2xl bg-[#F4EADF]">
<div className="w-12 h-10 border-2 border-[#8B8886] flex justify-center items-center rounded-2xl bg-header2">
<img src={Search} alt="search" />
</div>
<div className="flex items-center w-40 md:w-60 justify-between border-2 border-[#8B8886] rounded-2xl px-3 py-1 bg-[#F4EADF]">
<img src={Pic} className="w-8 h-8 rounded-full ml-1" alt="user" />
<p className="text-[#402E32] text-sm">سارا راد</p>
<img src={Arrow} className="w-4 h-4 ml-1" alt="arrow" />
</div>
<img src={Vector7} alt="vector" />
<button
onClick={toggleTheme}
className="w-12 h-10 border-2 border-[#8B8886] flex justify-center items-center rounded-2xl bg-header2 text-sm"
>
تغییر تم
</button>
</div>
</header>
<div className="flex items-center w-40 md:w-60 justify-between border-2 border-[#8B8886] rounded-2xl px-3 py-1 bg-header2">
<img src={Pic} className="w-8 h-8 rounded-full ml-1" alt="user" />
<p className="text-[#402E32] text-sm">سارا راد</p>
<img src={Arrow} className="w-4 h-4 ml-1" alt="arrow" />
</div>
<img src={Vector7} alt="vector" />
</header >
);
};

View File

@ -6,6 +6,42 @@ import { PiCoffee } from "react-icons/pi";
import { HiOutlineLogout } from "react-icons/hi";
import { FiMenu, FiX } from "react-icons/fi";
const SIDEBAR = {
logo: LogoDM,
navigation: [
{
id: 'dashboard',
path: '/dashboard',
icon: BiBarChartAlt2,
label: 'داشبورد',
},
{
id: 'cafe-management',
path: '/cafe-management',
icon: PiCoffee,
label: 'مدیریت کافه ها',
},
{
id: 'stats',
path: '/stats',
icon: AiOutlinePieChart,
label: 'آمار و تحلیل',
},
],
logout: {
icon: HiOutlineLogout,
label: 'خروج',
},
styles: {
activeColor: '#7F4629',
inactiveColor: '#402E32',
borderColor: '#D9CAB3',
padding: 'p-2.5',
gap: 'gap-2.5',
rounded: 'rounded-lg',
},
};
export default function Sidebar({ className, isOpen, setIsOpen }) {
const location = useLocation();
const navigate = useNavigate();
@ -19,9 +55,6 @@ export default function Sidebar({ className, isOpen, setIsOpen }) {
localStorage.removeItem('token');
localStorage.removeItem('adminInfo');
console.log('Tokens cleared from localStorage');
console.log('Current token:', localStorage.getItem('token'));
navigate('/login');
} catch (error) {
console.error('Logout error:', error);
@ -31,11 +64,46 @@ export default function Sidebar({ className, isOpen, setIsOpen }) {
const closeSidebar = () => setIsOpen(false);
const renderNavItem = (item) => {
const Icon = item.icon;
const active = isActive(item.path);
return (
<Link
key={item.id}
to={item.path}
onClick={closeSidebar}
className={`group flex items-center ${SIDEBAR.styles.gap} ${SIDEBAR.styles.rounded} ${SIDEBAR.styles.padding} transition-all duration-200 ${
active
? `bg-[${SIDEBAR.styles.activeColor}] shadow-md`
: `hover:bg-[${SIDEBAR.styles.activeColor}]`
}`}
>
<Icon
className={`w-5 h-5 flex-shrink-0 transition-colors ${
active
? "text-white"
: `text-[${SIDEBAR.styles.inactiveColor}] group-hover:text-white`
}`}
/>
<span
className={`text-sm font-medium transition-colors ${
active
? "text-white"
: `text-[${SIDEBAR.styles.inactiveColor}] group-hover:text-white`
}`}
>
{item.label}
</span>
</Link>
);
};
return (
<>
<button
onClick={() => setIsOpen(!isOpen)}
className="lg:hidden fixed top-4 right-4 z-[70] bg-[#7F4629] text-white p-2.5 rounded-lg shadow-lg"
className="lg:hidden fixed top-4 right-4 z-[70] bg-button1 text-white p-2.5 rounded-lg shadow-lg"
aria-label="Toggle menu"
>
{isOpen ? <FiX className="w-5 h-5" /> : <FiMenu className="w-5 h-5" />}
@ -57,103 +125,27 @@ export default function Sidebar({ className, isOpen, setIsOpen }) {
`}
>
<div className="flex justify-center mt-5 mb-2">
<img src={LogoDM} className="h-10 w-10 lg:h-12 lg:w-12" alt="Logo" />
<img src={SIDEBAR.logo} className="h-10 w-10 lg:h-12 lg:w-12" alt="Logo" />
</div>
<nav className="flex-1 px-3 mt-6 space-y-3 overflow-y-auto">
<Link
to="/dashboard"
onClick={closeSidebar}
className={`group flex items-center gap-2.5 rounded-lg p-2.5 transition-all duration-200 ${
isActive("/dashboard")
? "bg-[#7F4629] shadow-md"
: "hover:bg-[#7F4629]"
}`}
>
<BiBarChartAlt2
className={`w-5 h-5 flex-shrink-0 transition-colors ${
isActive("/dashboard")
? "text-white"
: "text-[#402E32] group-hover:text-white"
}`}
/>
<span
className={`text-sm font-medium transition-colors ${
isActive("/dashboard")
? "text-white"
: "text-[#402E32] group-hover:text-white"
}`}
>
داشبورد
</span>
</Link>
<Link
to="/cafe-management"
onClick={closeSidebar}
className={`group flex items-center gap-2.5 rounded-lg p-2.5 transition-all duration-200 ${
isActive("/cafe-management")
? "bg-[#7F4629] shadow-md"
: "hover:bg-[#7F4629]"
}`}
>
<PiCoffee
className={`w-5 h-5 flex-shrink-0 transition-colors ${
isActive("/cafe-management")
? "text-white"
: "text-[#402E32] group-hover:text-white"
}`}
/>
<span
className={`text-sm font-medium transition-colors ${
isActive("/cafe-management")
? "text-white"
: "text-[#402E32] group-hover:text-white"
}`}
>
مدیریت کافه ها
</span>
</Link>
<Link
to="/stats"
onClick={closeSidebar}
className={`group flex items-center gap-2.5 rounded-lg p-2.5 transition-all duration-200 ${
isActive("/stats")
? "bg-[#7F4629] shadow-md"
: "hover:bg-[#7F4629]"
}`}
>
<AiOutlinePieChart
className={`w-5 h-5 flex-shrink-0 transition-colors ${
isActive("/stats")
? "text-white"
: "text-[#402E32] group-hover:text-white"
}`}
/>
<span
className={`text-sm font-medium transition-colors ${
isActive("/stats")
? "text-white"
: "text-[#402E32] group-hover:text-white"
}`}
>
آمار و تحلیل
</span>
</Link>
{SIDEBAR.navigation.map(renderNavItem)}
</nav>
<div className="p-3 border-t border-[#D9CAB3]">
<div className={`p-3 border-t border-[${SIDEBAR.styles.borderColor}]`}>
<button
onClick={() => {
handleLogout();
closeSidebar();
}}
className="group flex items-center gap-2.5 rounded-lg p-2.5 transition-all duration-200 hover:bg-[#7F4629] w-full"
className={`group flex items-center ${SIDEBAR.styles.gap} ${SIDEBAR.styles.rounded} ${SIDEBAR.styles.padding} transition-all duration-200 hover:bg-button1 w-full`}
>
<HiOutlineLogout className="w-5 h-5 flex-shrink-0 text-[#402E32] transition-colors group-hover:text-white" />
{(() => {
const LogoutIcon = SIDEBAR.logout.icon;
return <LogoutIcon className="w-5 h-5 flex-shrink-0 text-[#402E32] transition-colors group-hover:text-white" />;
})()}
<span className="text-sm text-[#402E32] font-medium transition-colors group-hover:text-white">
خروج
{SIDEBAR.logout.label}
</span>
</button>
</div>

View File

@ -43,7 +43,7 @@ const CafeManagement = () => {
if (loading) {
return (
<div className="flex justify-center items-center h-screen">
<div className="text-[#7F4629] text-xl font-bold">در حال بارگذاری...</div>
<div className="text-button1 text-xl font-bold">در حال بارگذاری...</div>
</div>
);
}
@ -112,7 +112,7 @@ const CafeManagement = () => {
<td className="px-4 py-4 text-center">
<Link
to={`/edit-cafe/${cafe._id}`}
className="inline-flex items-center justify-center gap-2 border-2 border-[#BB8F70] px-6 py-2 rounded-3xl text-sm font-light text-[#402E32] hover:bg-[#7F4629] hover:text-white hover:border-[#7F4629] transition-all duration-300"
className="inline-flex items-center justify-center gap-2 border-2 border-[#BB8F70] px-6 py-2 rounded-3xl text-sm font-light text-[#402E32] hover:bg-button1 hover:text-white hover:border-button1 transition-all duration-300"
>
<span>ادیت</span>
<BiEdit className="w-4 h-4" />
@ -153,7 +153,7 @@ const CafeManagement = () => {
<Link
to={`/edit-cafe/${cafe._id}`}
className="flex justify-center items-center gap-2 w-full border-2 border-[#BB8F70] py-2 rounded-full text-sm font-medium text-[#402E32] hover:bg-[#7F4629] hover:text-white hover:border-[#7F4629] transition-all duration-300"
className="flex justify-center items-center gap-2 w-full border-2 border-[#BB8F70] py-2 rounded-full text-sm font-medium text-[#402E32] hover:bg-button1 hover:text-white hover:border-button1 transition-all duration-300"
>
<span>ادیت کافه</span>
<BiEdit className="w-4 h-4" />
@ -169,7 +169,7 @@ const CafeManagement = () => {
<section dir="rtl" className="w-full pt-24 max-w-full overflow-x-hidden">
{/* بخش دکمه اضافه کردن */}
<div className="flex items-center justify-between mb-8">
<button className="flex items-center justify-center gap-3 px-6 py-3 bg-[#7F4629] text-white rounded-3xl text-sm lg:text-base font-medium hover:bg-amber-950 transition-all duration-300 cursor-pointer">
<button className="flex items-center justify-center gap-3 px-6 py-3 bg-button1 text-white rounded-3xl text-sm lg:text-base font-medium hover:bg-amber-950 transition-all duration-300 cursor-pointer">
<span>افزودن شعبه جدید</span>
<img src={Vector9} alt="افزودن" className="w-5 h-5" />
</button>

View File

@ -161,7 +161,7 @@ export default function EditCafe() {
if (loading) {
return (
<div className="flex justify-center items-center h-screen">
<div className="text-[#7F4629] text-2xl font-bold">در حال بارگذاری...</div>
<div className="text-button1 text-2xl font-bold">در حال بارگذاری...</div>
</div>
);
}
@ -213,11 +213,11 @@ export default function EditCafe() {
<div className="flex gap-3 justify-end mb-6">
<button
onClick={() => navigate("/cafe-management")}
className="px-4 md:px-6 py-2 border-2 border-[#bb8f70] text-[#402e32] rounded-3xl hover:bg-[#7f4629] hover:text-white hover:border-[#7f4629] transition-all duration-300 text-sm md:text-base font-medium"
className="px-4 md:px-6 py-2 border-2 border-[#bb8f70] text-[#402e32] rounded-3xl hover:bg-button1 hover:text-white hover:border-button1 transition-all duration-300 text-sm md:text-base font-medium"
>
انصراف
</button>
<button className="px-4 md:px-6 py-2 bg-[#7f4629] text-white rounded-3xl hover:bg-[#5f494f] transition-all duration-300 text-sm md:text-base font-medium">
<button className="px-4 md:px-6 py-2 bg-button1 text-white rounded-3xl hover:bg-[#5f494f] transition-all duration-300 text-sm md:text-base font-medium">
تایید
</button>
</div>
@ -279,7 +279,7 @@ export default function EditCafe() {
<h2 className="font-bold text-[#402E32] text-base md:text-lg">دستهبندیها</h2>
<button
onClick={() => setIsEditMode(!isEditMode)}
className="flex items-center gap-2 text-[#7f4629] hover:text-[#5f494f] transition-colors"
className="flex items-center gap-2 text-button1 hover:text-[#5f494f] transition-colors"
title={isEditMode ? "خروج از حالت ویرایش" : "ویرایش دسته‌بندی‌ها"}
>
<img src={Vector16} alt="ویرایش" className="w-5 h-5" />
@ -308,7 +308,7 @@ export default function EditCafe() {
type="text"
value={editValue}
onChange={(e) => setEditValue(e.target.value)}
className="border-2 border-[#bb8f70] rounded-lg px-2 py-1 text-xs md:text-sm focus:outline-none focus:border-[#7f4629] min-w-[100px]"
className="border-2 border-[#bb8f70] rounded-lg px-2 py-1 text-xs md:text-sm focus:outline-none focus:border-button1 min-w-[100px]"
autoFocus
/>
</div>
@ -323,7 +323,7 @@ export default function EditCafe() {
<>
<BiEdit
onClick={() => handleEditCategory(idx)}
className="text-[#7f4629] cursor-pointer hover:text-[#5f494f] w-4 h-4 ml-1"
className="text-button1 cursor-pointer hover:text-[#5f494f] w-4 h-4 ml-1"
title="ویرایش"
/>
<IoMdClose
@ -341,7 +341,7 @@ export default function EditCafe() {
{isEditMode && !isAddingCategory && (
<button
onClick={() => setIsAddingCategory(true)}
className="flex-shrink-0 text-[#7f4629] hover:text-[#5f494f] font-bold text-sm md:text-base transition-colors whitespace-nowrap"
className="flex-shrink-0 text-button1 hover:text-[#5f494f] font-bold text-sm md:text-base transition-colors whitespace-nowrap"
>
+ افزودن
</button>
@ -369,7 +369,7 @@ export default function EditCafe() {
value={newCategory}
onChange={(e) => setNewCategory(e.target.value)}
placeholder="دسته جدید"
className="border-2 border-[#bb8f70] rounded-lg px-2 py-1 text-xs md:text-sm focus:outline-none focus:border-[#7f4629] min-w-[100px]"
className="border-2 border-[#bb8f70] rounded-lg px-2 py-1 text-xs md:text-sm focus:outline-none focus:border-button1 min-w-[100px]"
autoFocus
/>
</div>

View File

@ -71,7 +71,7 @@ export default function Login() {
<div className="flex items-center gap-4">
<img src={LogoDM} alt="Logo" className="h-10 w-10 md:h-12 md:w-12" />
<div className="relative">
<select className="appearance-none px-4 md:px-6 py-2 pr-4 pl-10 bg-white border-2 border-gray-300 rounded-xl text-sm focus:outline-none focus:border-[#7f4629] transition-colors cursor-pointer">
<select className="appearance-none px-4 md:px-6 py-2 pr-4 pl-10 bg-white border-2 border-gray-300 rounded-xl text-sm focus:outline-none focus:border-button1 transition-colors cursor-pointer">
<option>شهر</option>
<option>تهران</option>
<option>اصفهان</option>
@ -85,15 +85,15 @@ export default function Login() {
</div>
{/* Center Links (Hidden on Mobile) */}
<nav className="hidden md:flex items-center gap-8 font-bold text-[#402E32]">
<a href="#" className="hover:text-[#7f4629] transition-colors text-sm">خانه</a>
<a href="#" className="hover:text-[#7f4629] transition-colors text-sm">دسته بندی</a>
<a href="#" className="hover:text-[#7f4629] transition-colors text-sm">تماس با ما</a>
<a href="#" className="hover:text-[#7f4629] transition-colors text-sm">درباره ما</a>
<nav className="hidden md:flex items-center gap-8 font-bold text-primary">
<a href="#" className="hover:text-button1 transition-colors text-sm">خانه</a>
<a href="#" className="hover:text-button1 transition-colors text-sm">دسته بندی</a>
<a href="#" className="hover:text-button1 transition-colors text-sm">تماس با ما</a>
<a href="#" className="hover:text-button1 transition-colors text-sm">درباره ما</a>
</nav>
{/* Right Section */}
<button className="px-6 md:px-10 py-2 bg-[#7f4629] text-white rounded-full text-sm md:text-base font-medium hover:bg-[#5f494f] transition-colors">
<button className="px-6 md:px-10 py-2 bg-button1 text-white rounded-full text-sm md:text-base font-medium hover:bg-[#5f494f] transition-colors">
ثبت نام
</button>
</div>
@ -109,7 +109,7 @@ export default function Login() {
backgroundPosition: 'center',
backgroundAttachment: 'fixed'
}}
className="w-full md:w-1/2 flex items-start justify-center md:justify-start md:bg-[#f5f0e8] px-4 md:px-12 lg:px-24 py-8 md:py-16 relative">
className="w-full md:w-1/2 flex items-start justify-center md:justify-start md:bg-background px-4 md:px-12 lg:px-24 py-8 md:py-16 relative">
{/* Dark Overlay */}
<div className="absolute inset-0 bg-black/10 backdrop-blur-[1px] md:bg-transparent"></div>
<div className="w-full max-w-md relative z-10">
@ -122,7 +122,7 @@ export default function Login() {
{/* Header */}
<div className="mb-8">
<h1 className="text-2xl md:text-3xl font-bold mb-2 text-white md:text-[#402E32]">ورود ادمین</h1>
<h1 className="text-2xl md:text-3xl font-bold mb-2 text-white md:text-primary">ورود ادمین</h1>
<p className="text-sm md:text-base md:text-gray-700 text-white/80">دسترسی ویژه برای مدیریت و گزارشها</p>
</div>
@ -137,14 +137,14 @@ export default function Login() {
{/* Username Field */}
<div className="relative">
<label className="md:absolute -top-2.5 right-4 text-[#f5f0e8] md:text-[#402E32] md:bg-[#f5f0e8] z-50 px-1 text-sm">نام کاربری</label>
<label className="md:absolute -top-2.5 right-4 text-background md:text-primary md:bg-background z-50 px-1 text-sm">نام کاربری</label>
<div className="relative mt-2">
<input
type="text"
value={userName}
onChange={(e) => setUserName(e.target.value)}
placeholder="userName"
className="w-full pl-12 pr-4 py-3 border-2 bg-[#f5f0e8] border-gray-300 rounded-xl focus:outline-none focus:border-[#7f4629] transition-colors text-sm"
className="w-full pl-12 pr-4 py-3 border-2 bg-background border-gray-300 rounded-xl focus:outline-none focus:border-button1 transition-colors text-sm"
dir="ltr"
required
/>
@ -154,14 +154,14 @@ export default function Login() {
{/* Password Field */}
<div className="relative">
<label className="md:absolute -top-2.5 right-4 z-50 md:bg-[#f5f0e8] md:text-[#402E32] px-1 text-sm text-[#f5f0e8]">رمز عبور</label>
<label className="md:absolute -top-2.5 right-4 z-50 md:bg-background md:text-primary px-1 text-sm text-background">رمز عبور</label>
<div className="relative mt-2">
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="password"
className="w-full pl-12 pr-4 py-3 border-2 bg-[#f5f0e8] border-gray-300 rounded-xl focus:outline-none focus:border-[#7f4629] transition-colors text-sm"
className="w-full pl-12 pr-4 py-3 border-2 bg-background border-gray-300 rounded-xl focus:outline-none focus:border-button1 transition-colors text-sm"
dir="ltr"
required
/>
@ -171,7 +171,7 @@ export default function Login() {
{/* Forgot Password */}
<div className="text-right">
<a href="#" className="text-sm text-[#f5f0e8] hover:text-[#7f4629] transition-colors">
<a href="#" className="text-sm text-background hover:text-button1 transition-colors">
فراموشی رمز عبور؟
</a>
</div>
@ -180,7 +180,7 @@ export default function Login() {
<button
type="submit"
disabled={loading || !userName || !password}
className="w-full bg-[#7f4629] text-white py-3 rounded-full font-bold text-sm md:text-base hover:bg-[#5f494f] transition-all duration-300 shadow-lg hover:shadow-xl disabled:bg-gray-400 disabled:cursor-not-allowed"
className="w-full bg-button1 text-white py-3 rounded-full font-bold text-sm md:text-base hover:bg-[#5f494f] transition-all duration-300 shadow-lg hover:shadow-xl disabled:bg-gray-400 disabled:cursor-not-allowed"
>
{loading ? "در حال ورود..." : "ورود"}
</button>

View File

@ -1,4 +1,48 @@
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));
:root {
--color-primary: #7f4629;
--color-button1: #99582a;
--color-header: #f3efe7;
--color-header2: #e6dbcc;
--color-sidebar: #efeeee;
--color-background: #fdf8f4;
--font-sans: "Vazirmatn", system-ui, sans-serif;
}
.dark {
--color-primary: #d9cab3;
--color-button1: #99582a;
--color-header: #342e2c;
--color-header2: #5e5450;
--color-sidebar: #564c49;
--color-background: #272322;
}
html {
font-family: var(--font-sans);
}
body {
background-color: var(--background);
color: var(--foreground);
line-height: 1.6;
/* فاصله مناسب خطوط متن */
-webkit-font-smoothing: antialiased;
/* نرم‌تر شدن فونت */
text-rendering: optimizeLegibility;
/* خوانایی بهتر متن */
}
@font-face {
font-family: "MyEstedad";
@ -10,6 +54,33 @@
@theme {
--font-MyEstedad: "MyEstedad", sans-serif;
--color-primary: var(--color-primary);
--color-header: var(--color-header);
--color-sidebar: var(--color-sidebar);
--color-background: var(--color-background);
--color-button1: var(--color-button1);
/* --color-text1: var(--color-text1-menu-and-card);
--color-text2: var(--color-text2);
--color-text3: var(--color-text3);
--color-text4: var(--color-text4);
--color-btn1: var(--color-button1);
--color-btn2: var(--color-button2);
--color-btn3: var(--color-button3);
--color-primary1: var(--color-primary1);
--color-primary2: var(--color-primary2);
--color-primary3: var(--color-primary3);
--color-primary4: var(--color-primary4);
--color-primary5-dark: var(--color-primary5-dark);
--color-primary6-dark: var(--color-primary6-dark);
--color-bg-light: var(--color-background-light);
--color-bg-dark: var(--color-background-dark); */
}
@layer base {
@ -22,4 +93,38 @@
font-family: var(--font-MyEstedad);
direction: rtl;
}
}
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* دکمه‌ها فونت پروژه رو بگیرن */
button {
font-family: inherit;
cursor: pointer;
}
/* تصاویر و مدیاها ریسپانسیو باشن */
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
/* رنگ انتخاب متن (drag select) */
::selection {
background-color: var(--primary-200);
/* بک‌گراند انتخاب */
color: var(--primary-foreground);
/* رنگ متن انتخاب */
}