style(web): refactor dashboard icons to lucide-react for consistency

This commit is contained in:
dyzulk
2026-01-09 22:32:41 +07:00
parent 5958b93f84
commit b883715c26
7 changed files with 64 additions and 61 deletions

View File

@@ -6,7 +6,7 @@ import axios from "@/lib/axios";
import ComponentCard from "../common/ComponentCard"; import ComponentCard from "../common/ComponentCard";
import Button from "../ui/button/Button"; import Button from "../ui/button/Button";
import Badge from "../ui/badge/Badge"; import Badge from "../ui/badge/Badge";
import { TrashBinIcon, CopyIcon, CheckLineIcon, PlusIcon, LockIcon, BoltIcon } from "@/icons"; import { Trash2, Copy, Check, Plus, Lock, RefreshCw } from "lucide-react";
import { useToast } from "@/context/ToastContext"; import { useToast } from "@/context/ToastContext";
import ConfirmationModal from "../common/ConfirmationModal"; import ConfirmationModal from "../common/ConfirmationModal";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
@@ -130,7 +130,7 @@ export default function ApiKeyManagement() {
loading={isCreating} loading={isCreating}
disabled={!newKeyName.trim()} disabled={!newKeyName.trim()}
> >
<PlusIcon className="w-4 h-4 mr-2" /> <Plus className="w-4 h-4 mr-2" />
{t("btn_generate")} {t("btn_generate")}
</Button> </Button>
</form> </form>
@@ -149,7 +149,7 @@ export default function ApiKeyManagement() {
className="p-3 bg-white dark:bg-gray-800 border border-brand-200 dark:border-brand-500/30 rounded-lg text-brand-500 hover:bg-brand-50 dark:hover:bg-brand-500/10 transition-colors" className="p-3 bg-white dark:bg-gray-800 border border-brand-200 dark:border-brand-500/30 rounded-lg text-brand-500 hover:bg-brand-50 dark:hover:bg-brand-500/10 transition-colors"
title={t("copy_tooltip")} title={t("copy_tooltip")}
> >
{copied ? <CheckLineIcon className="w-5 h-5" /> : <CopyIcon className="w-5 h-5" />} {copied ? <Check className="w-5 h-5" /> : <Copy className="w-5 h-5" />}
</button> </button>
</div> </div>
<div className="mt-4 flex justify-end"> <div className="mt-4 flex justify-end">
@@ -188,7 +188,7 @@ export default function ApiKeyManagement() {
<td className="px-4 py-4"> <td className="px-4 py-4">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-full bg-gray-100 dark:bg-gray-800 flex items-center justify-center text-gray-500"> <div className="w-8 h-8 rounded-full bg-gray-100 dark:bg-gray-800 flex items-center justify-center text-gray-500">
<LockIcon className="w-4 h-4" /> <Lock className="w-4 h-4" />
</div> </div>
<span className="text-sm font-medium text-gray-800 dark:text-white/90">{key.name}</span> <span className="text-sm font-medium text-gray-800 dark:text-white/90">{key.name}</span>
</div> </div>
@@ -218,7 +218,7 @@ export default function ApiKeyManagement() {
className="p-2 text-gray-400 hover:text-brand-500 transition-colors disabled:opacity-50" className="p-2 text-gray-400 hover:text-brand-500 transition-colors disabled:opacity-50"
title={t("tooltip_regenerate")} title={t("tooltip_regenerate")}
> >
<BoltIcon className={`w-5 h-5 ${isRegenerating === key.id ? "animate-spin" : ""}`} /> <RefreshCw className={`w-5 h-5 ${isRegenerating === key.id ? "animate-spin" : ""}`} />
</button> </button>
<button <button
onClick={() => setConfirmRevokeId(key.id)} onClick={() => setConfirmRevokeId(key.id)}
@@ -226,7 +226,7 @@ export default function ApiKeyManagement() {
className="p-2 text-gray-400 hover:text-error-500 transition-colors disabled:opacity-50" className="p-2 text-gray-400 hover:text-error-500 transition-colors disabled:opacity-50"
title={t("tooltip_revoke")} title={t("tooltip_revoke")}
> >
<TrashBinIcon className="w-5 h-5" /> <Trash2 className="w-5 h-5" />
</button> </button>
</div> </div>
</td> </td>

View File

@@ -9,7 +9,7 @@ import {
TableRow, TableRow,
} from "../ui/table"; } from "../ui/table";
import Badge from "../ui/badge/Badge"; import Badge from "../ui/badge/Badge";
import { DownloadIcon, TrashBinIcon, EyeIcon } from "@/icons"; import { Download, Trash2, Eye } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import InputField from "../form/input/InputField"; import InputField from "../form/input/InputField";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
@@ -237,14 +237,14 @@ export default function CertificateTable({
className="p-2 text-gray-500 hover:text-brand-500 transition-colors" className="p-2 text-gray-500 hover:text-brand-500 transition-colors"
title={t("tooltip_view")} title={t("tooltip_view")}
> >
<EyeIcon className="w-5 h-5" /> <Eye className="w-5 h-5" />
</Link> </Link>
<button <button
onClick={() => onDelete(cert.uuid)} onClick={() => onDelete(cert.uuid)}
className="p-2 text-gray-500 hover:text-error-500 transition-colors" className="p-2 text-gray-500 hover:text-error-500 transition-colors"
title={t("tooltip_delete")} title={t("tooltip_delete")}
> >
<TrashBinIcon className="w-5 h-5" /> <Trash2 className="w-5 h-5" />
</button> </button>
</div> </div>
</TableCell> </TableCell>

View File

@@ -3,7 +3,7 @@
import React from "react"; import React from "react";
import { Modal } from "../ui/modal"; import { Modal } from "../ui/modal";
import Button from "../ui/button/Button"; import Button from "../ui/button/Button";
import { AlertIcon } from "@/icons"; import { AlertTriangle } from "lucide-react";
interface ConfirmationModalProps { interface ConfirmationModalProps {
isOpen: boolean; isOpen: boolean;
@@ -76,7 +76,7 @@ const ConfirmationModal: React.FC<ConfirmationModalProps> = ({
<div className="p-6"> <div className="p-6">
<div className="flex flex-col items-center text-center"> <div className="flex flex-col items-center text-center">
<div className={`mb-4 flex h-14 w-14 items-center justify-center rounded-full ${styles.iconBg}`}> <div className={`mb-4 flex h-14 w-14 items-center justify-center rounded-full ${styles.iconBg}`}>
<AlertIcon className={`h-7 w-7 ${styles.iconColor}`} /> <AlertTriangle className={`h-7 w-7 ${styles.iconColor}`} />
</div> </div>
<h3 className="mb-2 text-xl font-bold text-gray-800 dark:text-white/90"> <h3 className="mb-2 text-xl font-bold text-gray-800 dark:text-white/90">

View File

@@ -1,7 +1,7 @@
"use client"; "use client";
import React from "react"; import React from "react";
import Badge from "../ui/badge/Badge"; import Badge from "../ui/badge/Badge";
import { ArrowDownIcon, ArrowUpIcon, BoxIconLine, GroupIcon } from "@/icons"; import { ArrowUp, ArrowDown, Users, Package } from "lucide-react";
export const EcommerceMetrics = () => { export const EcommerceMetrics = () => {
return ( return (
@@ -9,7 +9,7 @@ export const EcommerceMetrics = () => {
{/* <!-- Metric Item Start --> */} {/* <!-- Metric Item Start --> */}
<div className="rounded-2xl border border-gray-200 bg-white p-5 dark:border-gray-800 dark:bg-white/[0.03] md:p-6"> <div className="rounded-2xl border border-gray-200 bg-white p-5 dark:border-gray-800 dark:bg-white/[0.03] md:p-6">
<div className="flex items-center justify-center w-12 h-12 bg-gray-100 rounded-xl dark:bg-gray-800"> <div className="flex items-center justify-center w-12 h-12 bg-gray-100 rounded-xl dark:bg-gray-800">
<GroupIcon className="text-gray-800 size-6 dark:text-white/90" /> <Users className="text-gray-800 size-6 dark:text-white/90" />
</div> </div>
<div className="flex items-end justify-between mt-5"> <div className="flex items-end justify-between mt-5">
@@ -22,7 +22,7 @@ export const EcommerceMetrics = () => {
</h4> </h4>
</div> </div>
<Badge color="success"> <Badge color="success">
<ArrowUpIcon /> <ArrowUp size={14} />
11.01% 11.01%
</Badge> </Badge>
</div> </div>
@@ -32,7 +32,7 @@ export const EcommerceMetrics = () => {
{/* <!-- Metric Item Start --> */} {/* <!-- Metric Item Start --> */}
<div className="rounded-2xl border border-gray-200 bg-white p-5 dark:border-gray-800 dark:bg-white/[0.03] md:p-6"> <div className="rounded-2xl border border-gray-200 bg-white p-5 dark:border-gray-800 dark:bg-white/[0.03] md:p-6">
<div className="flex items-center justify-center w-12 h-12 bg-gray-100 rounded-xl dark:bg-gray-800"> <div className="flex items-center justify-center w-12 h-12 bg-gray-100 rounded-xl dark:bg-gray-800">
<BoxIconLine className="text-gray-800 dark:text-white/90" /> <Package className="text-gray-800 size-6 dark:text-white/90" />
</div> </div>
<div className="flex items-end justify-between mt-5"> <div className="flex items-end justify-between mt-5">
<div> <div>
@@ -45,7 +45,7 @@ export const EcommerceMetrics = () => {
</div> </div>
<Badge color="error"> <Badge color="error">
<ArrowDownIcon className="text-error-500" /> <ArrowDown size={14} className="text-error-500" />
9.05% 9.05%
</Badge> </Badge>
</div> </div>

View File

@@ -4,7 +4,7 @@ import ComponentCard from "../../common/ComponentCard";
import Label from "../Label"; import Label from "../Label";
import Select from "../Select"; import Select from "../Select";
import MultiSelect from "../MultiSelect"; import MultiSelect from "../MultiSelect";
import { ChevronDownIcon } from "@/icons"; import { ChevronDown } from "lucide-react";
export default function SelectInputs() { export default function SelectInputs() {
const options = [ const options = [
@@ -40,7 +40,7 @@ export default function SelectInputs() {
className="dark:bg-dark-900" className="dark:bg-dark-900"
/> />
<span className="absolute text-gray-500 -translate-y-1/2 pointer-events-none right-3 top-1/2 dark:text-gray-400"> <span className="absolute text-gray-500 -translate-y-1/2 pointer-events-none right-3 top-1/2 dark:text-gray-400">
<ChevronDownIcon/> <ChevronDown size={18} />
</span> </span>
</div> </div>
</div> </div>

View File

@@ -3,21 +3,22 @@
import React from "react"; import React from "react";
import { useToast, ToastMessage, ToastType } from "@/context/ToastContext"; import { useToast, ToastMessage, ToastType } from "@/context/ToastContext";
import { import {
CheckCircleIcon, import {
ErrorIcon, CheckCircle,
AlertIcon, AlertCircle,
InfoIcon, AlertTriangle,
CloseIcon, Info,
} from "@/icons"; X,
} from "lucide-react";
const Toast: React.FC<{ toast: ToastMessage }> = ({ toast }) => { const Toast: React.FC<{ toast: ToastMessage }> = ({ toast }) => {
const { removeToast } = useToast(); const { removeToast } = useToast();
const icons = { const icons = {
success: <CheckCircleIcon className="w-5 h-5 text-green-500" />, success: <CheckCircle className="w-5 h-5 text-green-500" />,
error: <ErrorIcon className="w-5 h-5 text-red-500" />, error: <AlertCircle className="w-5 h-5 text-red-500" />,
warning: <AlertIcon className="w-5 h-5 text-yellow-500" />, warning: <AlertTriangle className="w-5 h-5 text-yellow-500" />,
info: <InfoIcon className="w-5 h-5 text-blue-500" />, info: <Info className="w-5 h-5 text-blue-500" />,
}; };
const bgClasses = { const bgClasses = {
@@ -45,7 +46,7 @@ const Toast: React.FC<{ toast: ToastMessage }> = ({ toast }) => {
aria-label="Close" aria-label="Close"
> >
<span className="sr-only">Close</span> <span className="sr-only">Close</span>
<CloseIcon className="w-4 h-4" /> <X className="w-4 h-4" />
</button> </button>
</div> </div>
); );

View File

@@ -8,21 +8,22 @@ import { useSidebar } from "../context/SidebarContext";
import useSWR from "swr"; import useSWR from "swr";
import axios from "@/lib/axios"; import axios from "@/lib/axios";
import { import {
BoxCubeIcon, LayoutGrid,
CalenderIcon, Calendar,
ChevronDownIcon, Users,
GridIcon, ShieldCheck,
HorizontaLDots, LifeBuoy,
ListIcon, FileText,
PageIcon, Send,
PieChartIcon, Mail,
PlugInIcon, Server,
TableIcon, Layers,
UserCircleIcon, UserCircle,
LockIcon, Settings,
MailIcon, KeyRound,
PaperPlaneIcon, ChevronDown,
} from "../icons/index"; Ellipsis,
} from "lucide-react";
type NavItem = { type NavItem = {
name: string; name: string;
@@ -37,23 +38,23 @@ type MenuGroup = {
}; };
const iconMap: Record<string, React.ReactNode> = { const iconMap: Record<string, React.ReactNode> = {
dashboard: <GridIcon />, dashboard: <LayoutGrid size={20} />,
calendar: <CalenderIcon />, calendar: <Calendar size={20} />,
users: <UserCircleIcon />, users: <Users size={20} />,
certificate: <BoxCubeIcon />, certificate: <ShieldCheck size={20} />,
"support-ticket": <PlugInIcon />, "support-ticket": <LifeBuoy size={20} />,
pages: <PageIcon />, pages: <FileText size={20} />,
email: <PaperPlaneIcon />, email: <Send size={20} />,
inbox: <MailIcon />, inbox: <Mail size={20} />,
smtp: <PaperPlaneIcon />, smtp: <Send size={20} />,
"server-settings": <BoxCubeIcon />, "server-settings": <Server size={20} />,
layers: <BoxCubeIcon />, layers: <Layers size={20} />,
"user-profile": <UserCircleIcon />, "user-profile": <UserCircle size={20} />,
settings: <BoxCubeIcon />, settings: <Settings size={20} />,
"api-key": <LockIcon />, "api-key": <KeyRound size={20} />,
}; };
const getIcon = (iconName: string) => iconMap[iconName] || <BoxCubeIcon />; const getIcon = (iconName: string) => iconMap[iconName] || <LayoutGrid size={20} />;
// Static items removed in favor of dynamic API data // Static items removed in favor of dynamic API data
@@ -101,7 +102,8 @@ const AppSidebar: React.FC = () => {
</span> </span>
)} )}
{(isExpanded || isHovered || isMobileOpen) && ( {(isExpanded || isHovered || isMobileOpen) && (
<ChevronDownIcon <ChevronDown
size={20}
className={`ml-auto w-5 h-5 transition-transform duration-200 ${ className={`ml-auto w-5 h-5 transition-transform duration-200 ${
openSubmenu?.type === menuType && openSubmenu?.type === menuType &&
openSubmenu?.index === index openSubmenu?.index === index
@@ -349,7 +351,7 @@ const AppSidebar: React.FC = () => {
try { return t(key); } catch { return group.title; } try { return t(key); } catch { return group.title; }
})() })()
) : ( ) : (
<HorizontaLDots /> <Ellipsis size={16} />
)} )}
</h2> </h2>
{renderMenuItems(group.items, group.title)} {renderMenuItems(group.items, group.title)}