feat: tab navigation

This commit is contained in:
2025-05-27 21:26:29 +02:00
parent c5c55f72b1
commit e983719601
6 changed files with 186 additions and 99 deletions

View File

@ -0,0 +1,27 @@
import type { FC } from "react";
import { barItems } from "../tabs";
export interface ISidebarProps {
activeTab: string;
onChangeTab: (tab: string) => void;
}
const Sidebar: FC<ISidebarProps> = ({ activeTab, onChangeTab }) => {
return (
<div className="hidden sm:flex flex-col gap-2 items-stretch min-w-80 w-80 p-5 pt-18 min-h-screen select-none bg-white/65 dark:bg-black/65 shadow-lg shadow-gray-300 dark:shadow-gray-700">
{barItems.map((item) => (
<div
key={item.tab}
onClick={() => onChangeTab(item.tab)}
className={`dark:text-gray-200 transition-colors text-md cursor-pointer p-4 rounded-lg flex flex-row items-center gap-3${
item.tab === activeTab ? " bg-gray-200 dark:bg-gray-900" : ""
}`}
>
{item.icon} {item.title}
</div>
))}
</div>
);
};
export default Sidebar;

View File

@ -0,0 +1,25 @@
import { type FC } from "react";
const Home: FC = () => {
return (
<div className="flex flex-col items-center gap-2 p-7">
<div className="w-24 h-24 sm:w-36 sm:h-36 overflow-hidden rounded-full flex items-center justify-center bg-gray-300">
{/* <User size={64} /> */}
<img
className="w-full h-full"
src="http://192.168.178.69:9000/guard-storage/profile_eff00028-2d9e-458d-8944-677855edc147_1748099702417601900.jpg"
alt="profile pic"
/>
</div>
<h1 className="dark:text-gray-200 text-gray-800 text-2xl select-none">
Welcome, Amir Adal
</h1>
<p className="text-gray-600 dark:text-gray-500 select-none text-center text-sm/normal sm:text-lg">
Manage your info, private and security to make Home Guard work better
for you.
</p>
</div>
);
};
export default Home;

View File

@ -0,0 +1,66 @@
import { ChevronRight } from "lucide-react";
import { type FC } from "react";
const PersonalInfo: FC = () => {
return (
<>
<h1 className="dark:text-gray-200 text-gray-800 text-2xl">
Your profile info in Home services
</h1>
<p className="text-gray-500 text-sm mt-2 sm:text-lg">
Personal info and options to manage it. You can make some of this info,
like your contact details, visible to others so they can reach you
easily. You can also see a summary of your profiles.
</p>
<div className="border dark:border-gray-800 border-gray-300 p-4 rounded mt-4">
<h3 className="dark:text-gray-300 text-gray-800">Basic info</h3>
<p className="text-gray-500 text-sm mt-2 mb-4">
Some info may be visible to other services and tools using Home Guard.{" "}
<a href="#" className="text-blue-500">
Learn more
</a>
</p>
{/* Profile Picture */}
<div className="flex flex-row items-center justify-between px-2 p-4 border-b gap-2 dark:border-b-gray-800 border-b-gray-100">
<div className="flex flex-col items-start gap-2">
<p className="text-sm dark:text-gray-400 font-medium text-gray-600">
Profile picture
</p>
<p className="text-sm dark:text-gray-500 text-gray-600">
Add a profile picture to personalize your account
</p>
</div>
<div>
<div className="w-16 h-16 overflow-hidden rounded-full dark:bg-gray-400 bg-gray-700">
<img
className="w-full h-full"
src="http://192.168.178.69:9000/guard-storage/profile_eff00028-2d9e-458d-8944-677855edc147_1748099702417601900.jpg"
alt="profile pic"
/>
</div>
</div>
</div>
{/* Name */}
<div className="flex flex-row items-center justify-between px-2 p-4 border-b dark:border-b-gray-800 border-b-gray-100">
<div className="flex flex-col items-start gap-2">
<p className="text-sm dark:text-gray-400 font-medium text-gray-600">
Name
</p>
<p className="text dark:text-gray-200 text-gray-800">Amir Adal</p>
</div>
<div>
<div className="text-gray-500">
<ChevronRight size={26} />
</div>
</div>
</div>
</div>
</>
);
};
export default PersonalInfo;

View File

@ -0,0 +1,29 @@
import { type FC } from "react";
import { barItems } from "../tabs";
export interface ITopBarProps {
activeTab: string;
onChangeTab: (tab: string) => void;
}
const TopBar: FC<ITopBarProps> = ({ activeTab, onChangeTab }) => {
return (
<div className="sm:hidden flex w-full overflow-x-auto sm:overflow-x-visible max-w-full min-w-full sm:justify-center sm:space-x-4 no-scrollbar shadow-md shadow-gray-300 dark:shadow-gray-700 dark:bg-black/70 bg-white/70 pt-14">
{barItems.map((item) => (
<div
key={item.tab}
onClick={() => onChangeTab(item.tab)}
className={`flex-shrink-0 transition-all border-b-4 px-4 py-2 min-w-[120px] sm:min-w-0 sm:flex-1 flex items-center justify-center cursor-pointer select-none whitespace-nowrap text-sm font-medium ${
item.tab === activeTab
? " border-b-4 border-b-blue-500 text-blue-500"
: " border-b-transparent text-gray-500"
}`}
>
{item.title}
</div>
))}
</div>
);
};
export default TopBar;

View File

@ -0,0 +1,19 @@
import { Home, Settings2, User } from "lucide-react";
export const barItems = [
{
icon: <Home />,
title: "Home",
tab: "home",
},
{
icon: <User />,
title: "Personal Info",
tab: "personal-info",
},
{
icon: <Settings2 />,
title: "Data & Personalization",
tab: "data-personalization",
},
];

View File

@ -1,20 +1,24 @@
import { type FC } from "react"; import { useState, type FC } from "react";
// import overlay from "@/assets/overlay.jpg"; // import overlay from "@/assets/overlay.jpg";
// import darkOverlay from "@/assets/dark-overlay.jpg"; // import darkOverlay from "@/assets/dark-overlay.jpg";
import { Card, CardContent } from "@/components/ui/card"; import { Card, CardContent } from "@/components/ui/card";
import { ChevronDown, ChevronRight } from "lucide-react"; import { ChevronRight } from "lucide-react";
import Sidebar from "@/components/Home/Sidebar";
import TopBar from "@/components/Home/TopBar";
import Home from "@/components/Home/Tabs/Home";
import PersonalInfo from "@/components/Home/Tabs/PersonalInfo";
const IndexPage: FC = () => { const IndexPage: FC = () => {
// console.log(overlay); const [tab, setTab] = useState<string>("home");
return ( return (
<div <div
className={`relative min-h-screen bg-cover bg-center bg-white dark:bg-black bg-[url(/overlay.jpg)] dark:bg-[url(/dark-overlay.jpg)]`} className={`relative min-h-screen bg-cover bg-center bg-white dark:bg-black bg-[url(/overlay.jpg)] dark:bg-[url(/dark-overlay.jpg)]`}
// style={{ backgroundImage: `url(${overlay})` }}
> >
<div className="relative z-10 flex items-center justify-center min-h-screen"> <div className="relative z-10 flex items-center justify-center min-h-screen">
<Card className="sm:w-[700px] sm:min-w-[700px] sm:max-w-96 sm:max-h-[calc(100vh-70px)] overflow-y-auto sm:min-h-auto min-h-screen w-full min-w-full shadow-lg bg-white/85 dark:bg-black/85 backdrop-blur-md"> <Card className="overflow-y-auto min-h-screen w-full min-w-full shadow-lg bg-white/85 dark:bg-black/85 backdrop-blur-md sm:rounded-none">
<div className="flex flex-col items-center sm:pt-0 relative"> <div className="flex flex-col items-center sm:pt-0 relative">
<div className="flex flex-row items-center absolute left-4 top-4"> <div className="flex flex-row items-center absolute left-4 top-4">
<img src="/icon.png" alt="icon" className="w-6 h-6" /> <img src="/icon.png" alt="icon" className="w-6 h-6" />
@ -28,102 +32,19 @@ const IndexPage: FC = () => {
{/* <LogIn className="w-8 h-8 text-gray-700 mb-4" /> */} {/* <LogIn className="w-8 h-8 text-gray-700 mb-4" /> */}
<CardContent className="w-full space-y-4 flex-1" spacing={false}> <CardContent className="w-full space-y-4 flex-1" spacing={false}>
<div className="flex flex-col w-full items-center gap-2 dark:bg-black/70 bg-white/70 shadow-md shadow-gray-300 dark:shadow-gray-700"> <div className="flex flex-row">
<div className="flex flex-col items-center gap-2 p-7 pt-14"> <Sidebar activeTab={tab} onChangeTab={(tab) => setTab(tab)} />
<div className="w-24 h-24 overflow-hidden rounded-full flex items-center justify-center bg-gray-300"> <div className="sm:p-4 max-w-full flex-1">
{/* <User size={64} /> */} <div className="flex flex-col w-full items-center gap-2">
<img <TopBar
className="w-full h-full" activeTab={tab}
src="http://192.168.178.69:9000/guard-storage/profile_eff00028-2d9e-458d-8944-677855edc147_1748099702417601900.jpg" onChangeTab={(tab) => setTab(tab)}
alt="profile pic"
/> />
</div> {tab === "home" && <Home />}
<h1 className="dark:text-gray-200 text-gray-800 text-2xl select-none"> {/* {tab === "personal-info" && <PersonalInfo />} */}
Amir Adal
</h1>
<div className="flex flex-row items-center gap-2 mr-[-10px] select-none">
<p className="text-gray-600 dark:text-gray-500">
qwer.009771@gmail.com
</p>
<div className="text-gray-600 dark:text-gray-500">
<ChevronDown size={18} />
</div>
</div>
</div>
<div className="flex w-full overflow-x-auto sm:overflow-x-visible max-w-full min-w-full sm:justify-center sm:space-x-4 no-scrollbar">
<div className="flex-shrink-0 px-4 py-2 min-w-[120px] sm:min-w-0 sm:flex-1 flex items-center justify-center border-b-4 border-b-blue-500 text-blue-500 cursor-pointer select-none whitespace-nowrap">
Home
</div>
<div className="flex-shrink-0 px-4 py-2 min-w-[140px] sm:min-w-0 sm:flex-1 flex items-center justify-center border-b-0 text-gray-500 cursor-pointer select-none whitespace-nowrap">
Personal Info
</div>
<div className="flex-shrink-0 px-4 py-2 min-w-[180px] sm:min-w-0 sm:flex-1 flex items-center justify-center border-b-0 text-gray-500 cursor-pointer select-none whitespace-nowrap">
Data & Personalization
</div>
</div>
</div> </div>
<div className="p-4"> <div className="p-4">
<h1 className="dark:text-gray-200 text-gray-800 text-2xl"> {tab === "personal-info" && <PersonalInfo />}
Your profile info in Home services
</h1>
<p className="text-gray-500 text-sm mt-2">
Personal info and options to manage it. You can make some of
this info, like your contact details, visible to others so
they can reach you easily. You can also see a summary of your
profiles.
</p>
<div className="border dark:border-gray-800 border-gray-300 p-4 rounded mt-4">
<h3 className="dark:text-gray-300 text-gray-800">
Basic info
</h3>
<p className="text-gray-500 text-sm mt-2 mb-4">
Some info may be visible to other services and tools using
Home Guard.{" "}
<a href="#" className="text-blue-500">
Learn more
</a>
</p>
{/* Profile Picture */}
<div className="flex flex-row items-center justify-between px-2 p-4 border-b gap-2 dark:border-b-gray-800 border-b-gray-100">
<div className="flex flex-col items-start gap-2">
<p className="text-sm dark:text-gray-400 font-medium text-gray-600">
Profile picture
</p>
<p className="text-sm dark:text-gray-500 text-gray-600">
Add a profile picture to personalize your account
</p>
</div>
<div>
<div className="w-16 h-16 overflow-hidden rounded-full dark:bg-gray-400 bg-gray-700">
<img
className="w-full h-full"
src="http://192.168.178.69:9000/guard-storage/profile_eff00028-2d9e-458d-8944-677855edc147_1748099702417601900.jpg"
alt="profile pic"
/>
</div>
</div>
</div>
{/* Name */}
<div className="flex flex-row items-center justify-between px-2 p-4 border-b dark:border-b-gray-800 border-b-gray-100">
<div className="flex flex-col items-start gap-2">
<p className="text-sm dark:text-gray-400 font-medium text-gray-600">
Name
</p>
<p className="text dark:text-gray-200 text-gray-800">
Amir Adal
</p>
</div>
<div>
<div className="text-gray-500">
<ChevronRight size={26} />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>