"fix: navItem no use links"
This commit is contained in:
parent
93363c875f
commit
322f4d8637
10
svgr.d.ts
vendored
Normal file
10
svgr.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
declare module '*.svg' {
|
||||||
|
import { FC, SVGProps } from 'react'
|
||||||
|
const content: FC<SVGProps<SVGElement>>
|
||||||
|
export default content
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '*.svg?url' {
|
||||||
|
const content: any
|
||||||
|
export default content
|
||||||
|
}
|
||||||
@ -1,13 +1,31 @@
|
|||||||
import type { NextConfig } from "next";
|
module.exports = {
|
||||||
|
webpack(config:any) {
|
||||||
|
// Grab the existing rule that handles SVG imports
|
||||||
|
const fileLoaderRule = config.module.rules.find((rule:any) =>
|
||||||
|
rule.test?.test?.('.svg'),
|
||||||
|
)
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
config.module.rules.push(
|
||||||
webpack(config) {
|
// Reapply the existing rule, but only for svg imports ending in ?url
|
||||||
config.module.rules.push({
|
{
|
||||||
test: /\.svg$/,
|
...fileLoaderRule,
|
||||||
use: ['@svgr/webpack'],
|
test: /\.svg$/i,
|
||||||
});
|
resourceQuery: /url/, // *.svg?url
|
||||||
return config;
|
},
|
||||||
|
// Convert all other *.svg imports to React components
|
||||||
|
{
|
||||||
|
test: /\.svg$/i,
|
||||||
|
issuer: fileLoaderRule.issuer,
|
||||||
|
resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url
|
||||||
|
use: ['@svgr/webpack'],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// Modify the file loader rule to ignore *.svg, since we have it handled now.
|
||||||
|
fileLoaderRule.exclude = /\.svg$/i
|
||||||
|
|
||||||
|
return config
|
||||||
},
|
},
|
||||||
};
|
|
||||||
|
|
||||||
export default nextConfig;
|
// ...other config
|
||||||
|
}
|
||||||
@ -35,6 +35,8 @@
|
|||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "15.2.3",
|
"eslint-config-next": "15.2.3",
|
||||||
|
"install": "^0.13.0",
|
||||||
|
"npm": "^11.2.0",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
|
|||||||
86
pnpm-lock.yaml
generated
86
pnpm-lock.yaml
generated
@ -81,6 +81,12 @@ importers:
|
|||||||
eslint-config-next:
|
eslint-config-next:
|
||||||
specifier: 15.2.3
|
specifier: 15.2.3
|
||||||
version: 15.2.3(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)
|
version: 15.2.3(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)
|
||||||
|
install:
|
||||||
|
specifier: ^0.13.0
|
||||||
|
version: 0.13.0
|
||||||
|
npm:
|
||||||
|
specifier: ^11.2.0
|
||||||
|
version: 11.2.0
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^4
|
specifier: ^4
|
||||||
version: 4.0.15
|
version: 4.0.15
|
||||||
@ -2633,6 +2639,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
||||||
engines: {node: '>=0.8.19'}
|
engines: {node: '>=0.8.19'}
|
||||||
|
|
||||||
|
install@0.13.0:
|
||||||
|
resolution: {integrity: sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==}
|
||||||
|
engines: {node: '>= 0.10'}
|
||||||
|
|
||||||
internal-slot@1.1.0:
|
internal-slot@1.1.0:
|
||||||
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
|
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@ -3011,6 +3021,78 @@ packages:
|
|||||||
node-releases@2.0.19:
|
node-releases@2.0.19:
|
||||||
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
|
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
|
||||||
|
|
||||||
|
npm@11.2.0:
|
||||||
|
resolution: {integrity: sha512-PcnFC6gTo9VDkxVaQ1/mZAS3JoWrDjAI+a6e2NgfYQSGDwftJlbdV0jBMi2V8xQPqbGcWaa7p3UP0SKF+Bhm2g==}
|
||||||
|
engines: {node: ^20.17.0 || >=22.9.0}
|
||||||
|
hasBin: true
|
||||||
|
bundledDependencies:
|
||||||
|
- '@isaacs/string-locale-compare'
|
||||||
|
- '@npmcli/arborist'
|
||||||
|
- '@npmcli/config'
|
||||||
|
- '@npmcli/fs'
|
||||||
|
- '@npmcli/map-workspaces'
|
||||||
|
- '@npmcli/package-json'
|
||||||
|
- '@npmcli/promise-spawn'
|
||||||
|
- '@npmcli/redact'
|
||||||
|
- '@npmcli/run-script'
|
||||||
|
- '@sigstore/tuf'
|
||||||
|
- abbrev
|
||||||
|
- archy
|
||||||
|
- cacache
|
||||||
|
- chalk
|
||||||
|
- ci-info
|
||||||
|
- cli-columns
|
||||||
|
- fastest-levenshtein
|
||||||
|
- fs-minipass
|
||||||
|
- glob
|
||||||
|
- graceful-fs
|
||||||
|
- hosted-git-info
|
||||||
|
- ini
|
||||||
|
- init-package-json
|
||||||
|
- is-cidr
|
||||||
|
- json-parse-even-better-errors
|
||||||
|
- libnpmaccess
|
||||||
|
- libnpmdiff
|
||||||
|
- libnpmexec
|
||||||
|
- libnpmfund
|
||||||
|
- libnpmorg
|
||||||
|
- libnpmpack
|
||||||
|
- libnpmpublish
|
||||||
|
- libnpmsearch
|
||||||
|
- libnpmteam
|
||||||
|
- libnpmversion
|
||||||
|
- make-fetch-happen
|
||||||
|
- minimatch
|
||||||
|
- minipass
|
||||||
|
- minipass-pipeline
|
||||||
|
- ms
|
||||||
|
- node-gyp
|
||||||
|
- nopt
|
||||||
|
- normalize-package-data
|
||||||
|
- npm-audit-report
|
||||||
|
- npm-install-checks
|
||||||
|
- npm-package-arg
|
||||||
|
- npm-pick-manifest
|
||||||
|
- npm-profile
|
||||||
|
- npm-registry-fetch
|
||||||
|
- npm-user-validate
|
||||||
|
- p-map
|
||||||
|
- pacote
|
||||||
|
- parse-conflict-json
|
||||||
|
- proc-log
|
||||||
|
- qrcode-terminal
|
||||||
|
- read
|
||||||
|
- semver
|
||||||
|
- spdx-expression-parse
|
||||||
|
- ssri
|
||||||
|
- supports-color
|
||||||
|
- tar
|
||||||
|
- text-table
|
||||||
|
- tiny-relative-date
|
||||||
|
- treeverse
|
||||||
|
- validate-npm-package-name
|
||||||
|
- which
|
||||||
|
|
||||||
nprogress@0.2.0:
|
nprogress@0.2.0:
|
||||||
resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==}
|
resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==}
|
||||||
|
|
||||||
@ -6463,6 +6545,8 @@ snapshots:
|
|||||||
|
|
||||||
imurmurhash@0.1.4: {}
|
imurmurhash@0.1.4: {}
|
||||||
|
|
||||||
|
install@0.13.0: {}
|
||||||
|
|
||||||
internal-slot@1.1.0:
|
internal-slot@1.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
@ -6815,6 +6899,8 @@ snapshots:
|
|||||||
|
|
||||||
node-releases@2.0.19: {}
|
node-releases@2.0.19: {}
|
||||||
|
|
||||||
|
npm@11.2.0: {}
|
||||||
|
|
||||||
nprogress@0.2.0: {}
|
nprogress@0.2.0: {}
|
||||||
|
|
||||||
nth-check@2.1.1:
|
nth-check@2.1.1:
|
||||||
|
|||||||
8
src/app/admin/admins/page.tsx
Normal file
8
src/app/admin/admins/page.tsx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default function Admins (){
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import "../../assets/css/admin.css"
|
import "../../assets/css/admin.css"
|
||||||
import Sidebar from "../components/sidebar";
|
import Sidebar from "../../components/admin/sidebar";
|
||||||
import Header from "../components/adminHeader";
|
import Header from "../../components/admin/adminHeader";
|
||||||
|
|
||||||
export default function Dashboard({ children }: { children: ReactNode }) {
|
export default function Dashboard({ children }: { children: ReactNode }) {
|
||||||
|
|
||||||
|
|||||||
8
src/app/admin/organizations/page.tsx
Normal file
8
src/app/admin/organizations/page.tsx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default function Organizations (){
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,38 +0,0 @@
|
|||||||
"use client"
|
|
||||||
import Image from "next/image";
|
|
||||||
import { icons } from "#/assets/icons"
|
|
||||||
import NavItem from "./navItem";
|
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
|
|
||||||
export default function Sidebar() {
|
|
||||||
|
|
||||||
const [activeItem, setActiveItem] = useState("home")
|
|
||||||
|
|
||||||
const handleNavMenu = (item:string) => {
|
|
||||||
setActiveItem(item)
|
|
||||||
console.log("active: ", item);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="sidebar r-m-0 d-flex flex-column pt-[25px] max-w-[90px] h-[100vh] relative ">
|
|
||||||
<div className="logo r-flex-center px-[20px] ">
|
|
||||||
<Image src={icons.logo} alt="Logo" className="scale-95" />
|
|
||||||
</div>
|
|
||||||
<div className="nav-menu r-column-center h-max pt-[160px] r-gap-40 ">
|
|
||||||
<NavItem link="#" iconSrc={icons.homeIcon} label="Home" isNavHome={true} isActive={activeItem === "home"} onClick={() => handleNavMenu("home") } />
|
|
||||||
<NavItem link="#" iconSrc={icons.companiesIcon} label="Organizations" isActive={activeItem === "organizations"} onClick={() => handleNavMenu("organizations") } />
|
|
||||||
<NavItem link="#" iconSrc={icons.userGroup} label="Admins" isActive={activeItem === "admins"} onClick={() => handleNavMenu("admins") } />
|
|
||||||
</div>
|
|
||||||
<div className="logout absolute bottom-[40px] left-[28px]">
|
|
||||||
<button type="button" className="cursor-pointer">
|
|
||||||
<Image src={icons.logout} alt="Logout" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
"use client"
|
|
||||||
import Image from "next/image";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { icons } from "#/assets/icons"
|
|
||||||
|
|
||||||
export default function Theme() {
|
|
||||||
|
|
||||||
const [theme, setTheme] = useState<string>(
|
|
||||||
localStorage.getItem("theme") || (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light")
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
document.body.setAttribute("data-theme", theme);
|
|
||||||
localStorage.setItem("theme", theme);
|
|
||||||
|
|
||||||
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
||||||
const handleChange = (e: MediaQueryListEvent) => {
|
|
||||||
const newTheme = e.matches ? "dark" : "light";
|
|
||||||
setTheme(newTheme);
|
|
||||||
};
|
|
||||||
|
|
||||||
mediaQuery.addEventListener("change", handleChange);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
mediaQuery.removeEventListener("change", handleChange);
|
|
||||||
};
|
|
||||||
}, [theme]);
|
|
||||||
|
|
||||||
const handleTheme = () => {
|
|
||||||
setTheme(theme === "light" ? "dark" : "light");
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div onClick={() => handleTheme()} className="theme">
|
|
||||||
<button type="button" className="icon-border">
|
|
||||||
{theme === "light" ?
|
|
||||||
<Image src={icons.sunIcon} alt="Light Mode" width={20} height={20} className="m-[2px]" />
|
|
||||||
:
|
|
||||||
<Image src={icons.moonIcon} alt="Dark Mode" width={20} height={20} className="m-[2px]" />
|
|
||||||
}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import Image from "next/image";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
export default function Home() {
|
|
||||||
return (
|
|
||||||
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
|
|
||||||
<Link href="/admin">See the admin page</Link>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
BIN
src/assets/icons.zip
Normal file
BIN
src/assets/icons.zip
Normal file
Binary file not shown.
62
src/assets/icons/index2.ts
Normal file
62
src/assets/icons/index2.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { GeneralHtmlAttr } from "#/lib/declarations";
|
||||||
|
|
||||||
|
const icons = {
|
||||||
|
CalendarMark: "Calendar Mark.svg",
|
||||||
|
Document: "Document.svg",
|
||||||
|
Ellipse2: "Ellipse 2.svg",
|
||||||
|
Group1: "Group (1).svg",
|
||||||
|
Group: "Group.svg",
|
||||||
|
Icons1: "Icons (1).svg",
|
||||||
|
Icons: "Icons.svg",
|
||||||
|
LineDuotone: "Line Duotone.svg",
|
||||||
|
MenuDots: "Menu Dots.svg",
|
||||||
|
NavItem: "NavItem.svg",
|
||||||
|
Path1: "Path (1).svg",
|
||||||
|
Path: "Path.svg",
|
||||||
|
Rectangle: "Rectangle.svg",
|
||||||
|
Search: "Search.svg",
|
||||||
|
Vector: "Vector.svg",
|
||||||
|
Add: "add.svg",
|
||||||
|
Archives: "archives.svg",
|
||||||
|
ArrowLeft: "arrowLeft.svg",
|
||||||
|
ArrowRight: "arrowRight.svg",
|
||||||
|
Buildings: "buildings.svg",
|
||||||
|
Checked: "checked.svg",
|
||||||
|
Cross: "cross.svg",
|
||||||
|
DocumentText: "document-text.svg",
|
||||||
|
Edit2: "edit-2.svg",
|
||||||
|
Element3White: "element-3-white.svg",
|
||||||
|
Element3: "element-3.svg",
|
||||||
|
EyeSlash: "eye-slash.svg",
|
||||||
|
Eye: "eye.svg",
|
||||||
|
IconAdd: "icon-add.svg",
|
||||||
|
Logo: "logo.svg",
|
||||||
|
LogoutRed: "logout-red.svg",
|
||||||
|
Logout: "logout.svg",
|
||||||
|
Maximize3: "maximize-3.svg",
|
||||||
|
Message: "message.svg",
|
||||||
|
Notifications: "notifications.svg",
|
||||||
|
PhFiles: "ph_files.svg",
|
||||||
|
PrimeFilePdf: "prime_file-pdf.svg",
|
||||||
|
PrimeFileWord: "prime_file-word.svg",
|
||||||
|
Profile2UserBlue: "profile-2user-blue.svg",
|
||||||
|
Profile2User: "profile-2user.svg",
|
||||||
|
Profile: "profile.svg",
|
||||||
|
Setting2: "setting-2.svg",
|
||||||
|
Setting3: "setting-3.svg",
|
||||||
|
Share: "share.svg",
|
||||||
|
Star: "star.svg",
|
||||||
|
Moon: "moon.svg",
|
||||||
|
Sun: "sun.svg",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Icon = ({ name, ...props }: { name: keyof typeof icons } & GeneralHtmlAttr) => {
|
||||||
|
const IconComponent = icons[name];
|
||||||
|
if (!IconComponent) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div {...props}>
|
||||||
|
<img src={`/icons/${IconComponent}`} alt={name} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,4 +1,4 @@
|
|||||||
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M8.10671 7.74667C8.04004 7.74 7.96004 7.74 7.88671 7.74667C6.30004 7.69334 5.04004 6.39334 5.04004 4.79334C5.04004 3.16 6.36004 1.83334 8.00004 1.83334C9.63337 1.83334 10.96 3.16 10.96 4.79334C10.9534 6.39334 9.69337 7.69334 8.10671 7.74667Z" stroke="#9FA8BC" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M8.10671 7.74667C8.04004 7.74 7.96004 7.74 7.88671 7.74667C6.30004 7.69334 5.04004 6.39334 5.04004 4.79334C5.04004 3.16 6.36004 1.83334 8.00004 1.83334C9.63337 1.83334 10.96 3.16 10.96 4.79334C10.9534 6.39334 9.69337 7.69334 8.10671 7.74667Z" stroke="#9FA8BC" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
|
||||||
<path d="M4.77348 10.2067C3.16014 11.2867 3.16014 13.0467 4.77348 14.12C6.60681 15.3467 9.61348 15.3467 11.4468 14.12C13.0601 13.04 13.0601 11.28 11.4468 10.2067C9.62014 8.98666 6.61348 8.98666 4.77348 10.2067Z" stroke="#9FA8BC" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M4.77348 10.2067C3.16014 11.2867 3.16014 13.0467 4.77348 14.12C6.60681 15.3467 9.61348 15.3467 11.4468 14.12C13.0601 13.04 13.0601 11.28 11.4468 10.2067C9.62014 8.98666 6.61348 8.98666 4.77348 10.2067Z" stroke="#9FA8BC" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 737 B After Width: | Height: | Size: 731 B |
@ -7,6 +7,7 @@ import { DropdownMenu } from "radix-ui";
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Theme from "./theme";
|
import Theme from "./theme";
|
||||||
|
|
||||||
|
import ProfilePicture from "../../assets/icons/profile.svg"
|
||||||
|
|
||||||
export default function AdminHeader() {
|
export default function AdminHeader() {
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
@ -17,6 +18,8 @@ export default function AdminHeader() {
|
|||||||
<p className="name text-[26px]">Bienvenue, <span>Ken B.</span> </p>
|
<p className="name text-[26px]">Bienvenue, <span>Ken B.</span> </p>
|
||||||
<div className="r-flex-between justify-center items-center r-gap-12">
|
<div className="r-flex-between justify-center items-center r-gap-12">
|
||||||
<Theme />
|
<Theme />
|
||||||
|
{/* <ProfilePicture /> */}
|
||||||
|
|
||||||
<button type="button" className="icon-border">
|
<button type="button" className="icon-border">
|
||||||
<Image src={icons.notificationsIcon} alt="Notifications" />
|
<Image src={icons.notificationsIcon} alt="Notifications" />
|
||||||
</button>
|
</button>
|
||||||
@ -7,13 +7,12 @@ interface ItemProps {
|
|||||||
label: string;
|
label: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
isNavHome?: boolean;
|
isNavHome?: boolean;
|
||||||
onClick: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function NavItem({ link, iconSrc, label, isActive, isNavHome, onClick }: ItemProps) {
|
export default function NavItem({ link, iconSrc, label, isActive, isNavHome }: ItemProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Link href={link} onClick={onClick} className={`nav-item r-flex-center ${isActive ? "active" : ""}`} >
|
<Link href={link} className={`nav-item r-flex-center ${isActive ? "active" : ""}`} >
|
||||||
<Image src={iconSrc} alt={label} className={`scale-100 ${isNavHome ? "nav-home" : ""}`} />
|
<Image src={iconSrc} alt={label} className={`scale-100 ${isNavHome ? "nav-home" : ""}`} />
|
||||||
</Link>
|
</Link>
|
||||||
</>
|
</>
|
||||||
32
src/components/admin/sidebar.tsx
Normal file
32
src/components/admin/sidebar.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
"use client"
|
||||||
|
import Image from "next/image";
|
||||||
|
import { icons } from "#/assets/icons"
|
||||||
|
import NavItem from "./navItem";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
|
||||||
|
export default function Sidebar() {
|
||||||
|
|
||||||
|
const pathname = usePathname();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="sidebar r-m-0 d-flex flex-column pt-[25px] max-w-[90px] h-[100vh] relative ">
|
||||||
|
<div className="logo r-flex-center px-[20px] ">
|
||||||
|
<Image src={icons.logo} alt="Logo" className="scale-95" />
|
||||||
|
</div>
|
||||||
|
<div className="nav-menu r-column-center h-max pt-[160px] r-gap-40 ">
|
||||||
|
<NavItem link="/admin/home" iconSrc={icons.homeIcon} label="Home" isNavHome={true} isActive={(pathname === "/admin/") || (pathname === "/admin/home")} />
|
||||||
|
<NavItem link="/admin/organizations" iconSrc={icons.companiesIcon} label="Organizations" isActive={pathname.startsWith("/admin/organizations")} />
|
||||||
|
<NavItem link="/admin/admins" iconSrc={icons.userGroup} label="Admins" isActive={pathname.startsWith("/admin/admins")} />
|
||||||
|
</div>
|
||||||
|
<div className="logout absolute bottom-[40px] left-[28px]">
|
||||||
|
<Link href="#" className="cursor-pointer">
|
||||||
|
<Image src={icons.logout} alt="Logout" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
54
src/components/admin/theme.tsx
Normal file
54
src/components/admin/theme.tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"use client"
|
||||||
|
import Image from "next/image";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { icons } from "#/assets/icons"
|
||||||
|
|
||||||
|
export default function Theme() {
|
||||||
|
const [theme, setTheme] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
const savedTheme = localStorage.getItem("theme") ||
|
||||||
|
(window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
|
||||||
|
|
||||||
|
setTheme(savedTheme);
|
||||||
|
document.body.setAttribute("data-theme", savedTheme);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleTheme = () => {
|
||||||
|
const newTheme = theme === "light" ? "dark" : "light";
|
||||||
|
setTheme(newTheme);
|
||||||
|
localStorage.setItem("theme", newTheme);
|
||||||
|
document.body.setAttribute("data-theme", newTheme);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (theme === null) return;
|
||||||
|
|
||||||
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||||
|
const handleChange = (e: MediaQueryListEvent) => {
|
||||||
|
const newTheme = e.matches ? "dark" : "light";
|
||||||
|
setTheme(newTheme);
|
||||||
|
localStorage.setItem("theme", newTheme);
|
||||||
|
document.body.setAttribute("data-theme", newTheme);
|
||||||
|
};
|
||||||
|
|
||||||
|
mediaQuery.addEventListener("change", handleChange);
|
||||||
|
return () => mediaQuery.removeEventListener("change", handleChange);
|
||||||
|
}, [theme]);
|
||||||
|
|
||||||
|
if (theme === null) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div onClick={handleTheme} className="theme">
|
||||||
|
<button type="button" className="icon-border">
|
||||||
|
{theme === "light" ? (
|
||||||
|
<Image src={icons.sunIcon} alt="Light Mode" width={20} height={20} className="m-[2px]" />
|
||||||
|
) : (
|
||||||
|
<Image src={icons.moonIcon} alt="Dark Mode" width={20} height={20} className="m-[2px]" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
3
src/lib/declarations.ts
Normal file
3
src/lib/declarations.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// src/lib/declarations.ts
|
||||||
|
|
||||||
|
export type GeneralHtmlAttr = React.HTMLProps<HTMLDivElement> | React.HTMLProps<HTMLImageElement>;
|
||||||
@ -19,9 +19,10 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"#/*": ["./src/*"]
|
"#/*": ["./src/*"],
|
||||||
|
"@/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"include": ["svgr.d.ts", "next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user