337 lines
16 KiB
TypeScript
337 lines
16 KiB
TypeScript
'use client';
|
|
|
|
/* ======================================================
|
|
IMPORTS
|
|
====================================================== */
|
|
import { useState } from 'react';
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
import { IRootState } from '@/store';
|
|
|
|
import {
|
|
toggleAnimation,
|
|
toggleLayout,
|
|
toggleMenu,
|
|
toggleNavbar,
|
|
toggleRTL,
|
|
toggleTheme,
|
|
toggleSemidark,
|
|
resetToggleSidebar,
|
|
} from '@/store/themeConfigSlice';
|
|
|
|
// Icons
|
|
import IconSettings from '@/components/icon/icon-settings';
|
|
import IconX from '@/components/icon/icon-x';
|
|
import IconSun from '@/components/icon/icon-sun';
|
|
import IconMoon from '@/components/icon/icon-moon';
|
|
import IconLaptop from '@/components/icon/icon-laptop';
|
|
|
|
/* ======================================================
|
|
COMPONENT
|
|
====================================================== */
|
|
const Setting = () => {
|
|
const themeConfig = useSelector((state: IRootState) => state.themeConfig);
|
|
const dispatch = useDispatch();
|
|
const [showCustomizer, setShowCustomizer] = useState(false);
|
|
|
|
return (
|
|
<div>
|
|
{/* ==================================================
|
|
OVERLAY (Background blur when drawer opens)
|
|
================================================== */}
|
|
<div
|
|
className={`fixed inset-0 z-[51] bg-black/70 backdrop-blur-sm ${
|
|
showCustomizer ? 'block' : 'hidden'
|
|
}`}
|
|
onClick={() => setShowCustomizer(false)}
|
|
/>
|
|
|
|
{/* ==================================================
|
|
CUSTOMIZER DRAWER
|
|
Footer-style dark background applied
|
|
================================================== */}
|
|
<nav
|
|
className={`
|
|
fixed top-0 bottom-0 z-[52]
|
|
w-full max-w-[400px]
|
|
transition-all duration-300
|
|
border-l border-white/10
|
|
shadow-2xl
|
|
${showCustomizer ? 'ltr:right-0 rtl:left-0' : 'ltr:-right-[400px] rtl:-left-[400px]'}
|
|
`}
|
|
>
|
|
{/* ==================================================
|
|
FOOTER-STYLE BACKGROUND LAYER
|
|
================================================== */}
|
|
<div className="absolute inset-0 bg-[#0b0d1c]">
|
|
{/* Blue glow */}
|
|
<div className="absolute top-24 left-6 w-24 h-24 bg-blue-500/40 blur-3xl rounded-full" />
|
|
|
|
{/* Purple glow */}
|
|
<div className="absolute bottom-32 -left-10 w-40 h-40 bg-purple-600/40 blur-3xl rounded-full" />
|
|
|
|
{/* Cyan glow */}
|
|
<div className="absolute top-1/2 -right-10 w-32 h-32 bg-cyan-400/30 blur-3xl rounded-full" />
|
|
</div>
|
|
|
|
{/* ==================================================
|
|
TOGGLE BUTTON
|
|
================================================== */}
|
|
<button
|
|
type="button"
|
|
className="
|
|
absolute inset-y-0 my-auto
|
|
flex h-12 w-12 items-center justify-center
|
|
bg-gradient-to-br from-blue-600 to-cyan-400
|
|
text-white shadow-lg
|
|
ltr:-left-12 rtl:-right-12
|
|
rounded-full
|
|
z-10
|
|
"
|
|
onClick={() => setShowCustomizer(!showCustomizer)}
|
|
>
|
|
<IconSettings className="h-5 w-5 animate-[spin_6s_linear_infinite]" />
|
|
</button>
|
|
|
|
{/* ==================================================
|
|
CONTENT (Glass effect over footer bg)
|
|
================================================== */}
|
|
<div className="relative h-full overflow-y-auto px-5 py-6 text-white backdrop-blur-xl bg-black/40">
|
|
|
|
{/* HEADER */}
|
|
<div className="relative mb-6 text-center">
|
|
<button
|
|
type="button"
|
|
className="absolute right-0 top-0 text-gray-400 hover:text-white"
|
|
onClick={() => setShowCustomizer(false)}
|
|
>
|
|
<IconX className="h-5 w-5" />
|
|
</button>
|
|
|
|
<h4 className="text-lg font-semibold">
|
|
Template Customizer
|
|
</h4>
|
|
|
|
<p className="text-sm text-gray-400">
|
|
UI preferences (saved automatically)
|
|
</p>
|
|
</div>
|
|
|
|
{/* ==================================================
|
|
SETTINGS SECTIONS
|
|
================================================== */}
|
|
<div className="space-y-5">
|
|
|
|
{/* COLOR SCHEME */}
|
|
<section className="rounded-xl bg-white/5 border border-white/10 p-4">
|
|
<h5 className="font-medium mb-2">Color Scheme</h5>
|
|
|
|
<div className="grid grid-cols-3 gap-2">
|
|
<button
|
|
className={`btn ${
|
|
themeConfig.theme === 'light'
|
|
? 'btn-primary'
|
|
: 'btn-outline-primary'
|
|
}`}
|
|
onClick={() => dispatch(toggleTheme('light'))}
|
|
>
|
|
<IconSun className="w-4 h-4 mr-1" /> Light
|
|
</button>
|
|
|
|
<button
|
|
className={`btn ${
|
|
themeConfig.theme === 'dark'
|
|
? 'btn-primary'
|
|
: 'btn-outline-primary'
|
|
}`}
|
|
onClick={() => dispatch(toggleTheme('dark'))}
|
|
>
|
|
<IconMoon className="w-4 h-4 mr-1" /> Dark
|
|
</button>
|
|
|
|
<button
|
|
className={`btn ${
|
|
themeConfig.theme === 'system'
|
|
? 'btn-primary'
|
|
: 'btn-outline-primary'
|
|
}`}
|
|
onClick={() => dispatch(toggleTheme('system'))}
|
|
>
|
|
<IconLaptop className="w-4 h-4 mr-1" /> System
|
|
</button>
|
|
</div>
|
|
</section>
|
|
|
|
{/* NAVIGATION */}
|
|
<section className="rounded-xl bg-white/5 border border-white/10 p-4">
|
|
<h5 className="font-medium mb-2">Navigation</h5>
|
|
|
|
<div className="grid grid-cols-3 gap-2">
|
|
<button
|
|
className={`btn ${
|
|
themeConfig.menu === 'horizontal'
|
|
? 'btn-primary'
|
|
: 'btn-outline-primary'
|
|
}`}
|
|
onClick={() => {
|
|
dispatch(toggleMenu('horizontal'));
|
|
dispatch(resetToggleSidebar());
|
|
}}
|
|
>
|
|
Horizontal
|
|
</button>
|
|
|
|
<button
|
|
className={`btn ${
|
|
themeConfig.menu === 'vertical'
|
|
? 'btn-primary'
|
|
: 'btn-outline-primary'
|
|
}`}
|
|
onClick={() => {
|
|
dispatch(toggleMenu('vertical'));
|
|
dispatch(resetToggleSidebar());
|
|
}}
|
|
>
|
|
Vertical
|
|
</button>
|
|
|
|
<button
|
|
className={`btn ${
|
|
themeConfig.menu === 'collapsible-vertical'
|
|
? 'btn-primary'
|
|
: 'btn-outline-primary'
|
|
}`}
|
|
onClick={() => {
|
|
dispatch(toggleMenu('collapsible-vertical'));
|
|
dispatch(resetToggleSidebar());
|
|
}}
|
|
>
|
|
Collapsible
|
|
</button>
|
|
</div>
|
|
|
|
<label className="mt-4 flex items-center gap-2 text-sm text-gray-300">
|
|
<input
|
|
type="checkbox"
|
|
className="form-checkbox"
|
|
checked={themeConfig.semidark}
|
|
onChange={(e) =>
|
|
dispatch(toggleSemidark(e.target.checked))
|
|
}
|
|
/>
|
|
Semi-dark Header & Sidebar
|
|
</label>
|
|
</section>
|
|
|
|
{/* LAYOUT */}
|
|
<section className="rounded-xl bg-white/5 border border-white/10 p-4">
|
|
<h5 className="font-medium mb-3">Layout</h5>
|
|
|
|
<div className="flex gap-2">
|
|
<button
|
|
className={`btn flex-1 ${
|
|
themeConfig.layout === 'boxed-layout'
|
|
? 'btn-primary'
|
|
: 'btn-outline-primary'
|
|
}`}
|
|
onClick={() =>
|
|
dispatch(toggleLayout('boxed-layout'))
|
|
}
|
|
>
|
|
Boxed
|
|
</button>
|
|
|
|
<button
|
|
className={`btn flex-1 ${
|
|
themeConfig.layout === 'full'
|
|
? 'btn-primary'
|
|
: 'btn-outline-primary'
|
|
}`}
|
|
onClick={() =>
|
|
dispatch(toggleLayout('full'))
|
|
}
|
|
>
|
|
Full
|
|
</button>
|
|
</div>
|
|
</section>
|
|
|
|
{/* DIRECTION */}
|
|
<section className="rounded-xl bg-white/5 border border-white/10 p-4">
|
|
<h5 className="font-medium mb-3">Direction</h5>
|
|
|
|
<div className="flex gap-2">
|
|
<button
|
|
className={`btn flex-1 ${
|
|
themeConfig.rtlClass === 'ltr'
|
|
? 'btn-primary'
|
|
: 'btn-outline-primary'
|
|
}`}
|
|
onClick={() => dispatch(toggleRTL('ltr'))}
|
|
>
|
|
LTR
|
|
</button>
|
|
|
|
<button
|
|
className={`btn flex-1 ${
|
|
themeConfig.rtlClass === 'rtl'
|
|
? 'btn-primary'
|
|
: 'btn-outline-primary'
|
|
}`}
|
|
onClick={() => dispatch(toggleRTL('rtl'))}
|
|
>
|
|
RTL
|
|
</button>
|
|
</div>
|
|
</section>
|
|
|
|
{/* NAVBAR */}
|
|
<section className="rounded-xl bg-white/5 border border-white/10 p-4">
|
|
<h5 className="font-medium mb-2">Navbar</h5>
|
|
|
|
<div className="flex gap-3 text-sm text-gray-300">
|
|
{['navbar-sticky', 'navbar-floating', 'navbar-static'].map(
|
|
(val) => (
|
|
<label key={val} className="flex items-center gap-1">
|
|
<input
|
|
type="radio"
|
|
className="form-radio"
|
|
checked={themeConfig.navbar === val}
|
|
onChange={() => dispatch(toggleNavbar(val))}
|
|
/>
|
|
{val.replace('navbar-', '')}
|
|
</label>
|
|
)
|
|
)}
|
|
</div>
|
|
</section>
|
|
|
|
{/* PAGE ANIMATION */}
|
|
<section className="rounded-xl bg-white/5 border border-white/10 p-4">
|
|
<h5 className="font-medium mb-2">Page Transition</h5>
|
|
|
|
<select
|
|
className="w-full rounded-lg bg-black/40 border border-white/15 text-white px-3 py-2"
|
|
value={themeConfig.animation}
|
|
onChange={(e) =>
|
|
dispatch(toggleAnimation(e.target.value))
|
|
}
|
|
>
|
|
<option value=" ">None</option>
|
|
<option value="animate__fadeIn">Fade</option>
|
|
<option value="animate__fadeInUp">Fade Up</option>
|
|
<option value="animate__fadeInDown">Fade Down</option>
|
|
<option value="animate__fadeInLeft">Fade Left</option>
|
|
<option value="animate__fadeInRight">Fade Right</option>
|
|
<option value="animate__zoomIn">Zoom</option>
|
|
</select>
|
|
</section>
|
|
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Setting;
|