@goplusvn/core 0.1.46 → 0.1.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44,6 +44,41 @@ export const branchSchema = z.object({
44
44
  .nullable()
45
45
  .or(z.literal("")),
46
46
 
47
+ position: z
48
+ .string()
49
+ .max(255, "Chức vụ tối đa 255 ký tự")
50
+ .trim()
51
+ .optional()
52
+ .nullable(),
53
+
54
+ representativePhone: z
55
+ .string()
56
+ .max(20, "Số điện thoại tối đa 20 ký tự")
57
+ .trim()
58
+ .optional()
59
+ .nullable(),
60
+
61
+ citizenId: z
62
+ .string()
63
+ .max(50, "Số CCCD tối đa 50 ký tự")
64
+ .trim()
65
+ .optional()
66
+ .nullable(),
67
+
68
+ taxCode: z
69
+ .string()
70
+ .max(50, "Mã số thuế tối đa 50 ký tự")
71
+ .trim()
72
+ .optional()
73
+ .nullable(),
74
+
75
+ bankAccount: z
76
+ .string()
77
+ .max(255, "Số tài khoản tối đa 255 ký tự")
78
+ .trim()
79
+ .optional()
80
+ .nullable(),
81
+
47
82
  status: z.enum(["active", "inactive"]).default("active"),
48
83
  });
49
84
 
@@ -3,6 +3,8 @@ import { z } from "zod";
3
3
  export const userSchema = z.object({
4
4
  name: z.string().min(1, "Tên hiển thị là bắt buộc"),
5
5
  email: z.string().email("Email không hợp lệ"),
6
+ phoneNumber: z.string().optional(),
7
+ address: z.string().optional(),
6
8
  // Support both boolean and status string, normalize to boolean
7
9
  isActive: z.preprocess((val) => {
8
10
  if (typeof val === "boolean") return val;
@@ -32,6 +32,8 @@ export const warehouseSchema = z.object({
32
32
  .or(z.literal(""))
33
33
  .transform((val) => val || ""),
34
34
 
35
+ branchId: z.string().optional(),
36
+
35
37
  status: z.preprocess((val) => {
36
38
  // Hỗ trợ boolean từ switch field (true -> active, false -> inactive)
37
39
  if (typeof val === "boolean") {
@@ -400,7 +400,7 @@ export function UnifiedProfileDialog({
400
400
 
401
401
  return (
402
402
  <Dialog open={open} onOpenChange={onOpenChange}>
403
- <DialogContent className="w-[100dvw] h-[100dvh] max-w-none max-h-none sm:w-auto sm:max-w-5xl sm:h-[85vh] flex flex-col p-0 gap-0 overflow-hidden border border-[#dee3e9] dark:border-[#1c1e21] shadow-[0_12px_32px_rgba(0,0,0,0.1)] bg-[#ffffff] dark:bg-[#0a1317] rounded-none sm:rounded-[12px] [&>button.absolute]:hidden">
403
+ <DialogContent className="w-[100dvw] h-[100dvh] max-w-none max-h-none sm:w-auto sm:max-w-5xl sm:h-[85vh] flex flex-col p-0 gap-0 overflow-hidden border border-border shadow-[0_12px_32px_rgba(0,0,0,0.1)] bg-background rounded-none sm:rounded-[12px] [&>button.absolute]:hidden">
404
404
  <DialogHeader className="sr-only">
405
405
  <DialogTitle>
406
406
  {mode === "create" ? "Tạo mới" : "Chỉnh sửa"}
@@ -409,33 +409,33 @@ export function UnifiedProfileDialog({
409
409
 
410
410
  <div className="flex flex-col w-full h-full overflow-hidden">
411
411
  {/* TOP HEADER: Profile Info + Actions */}
412
- <div className="shrink-0 flex flex-col border-b border-[#e2e8f0] dark:border-[#334155] bg-[#f8fafc] dark:bg-[#0f172a] px-6 pt-5 pb-0">
412
+ <div className="shrink-0 flex flex-col border-b border-border bg-muted px-6 pt-5 pb-0">
413
413
  <div className="flex flex-col sm:flex-row sm:items-start justify-between gap-4 pb-5">
414
414
  {/* Profile Header */}
415
415
  <div className="flex items-center gap-4">
416
416
  <div className="relative">
417
- <Avatar className="h-12 w-12 sm:h-14 sm:w-14 rounded-full border border-[#e2e8f0] dark:border-[#334155]">
417
+ <Avatar className="h-12 w-12 sm:h-14 sm:w-14 rounded-full border border-border">
418
418
  <AvatarImage
419
419
  src={displayData.avatar}
420
420
  className="object-cover rounded-full"
421
421
  />
422
- <AvatarFallback className="text-[16px] sm:text-[18px] font-semibold bg-[#1641CE] text-white dark:bg-[#1E40AF] dark:text-white rounded-full">
422
+ <AvatarFallback className="text-[16px] sm:text-[18px] font-semibold bg-primary text-primary-foreground rounded-full">
423
423
  {getInitials(profileData.name)}
424
424
  </AvatarFallback>
425
425
  </Avatar>
426
426
  <div
427
427
  className={cn(
428
- "absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 sm:w-4 sm:h-4 border-[2px] border-[#f8fafc] dark:border-[#0f172a] rounded-full z-10",
429
- isActive ? "bg-[#10b981]" : "bg-[#cbd5e1]"
428
+ "absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 sm:w-4 sm:h-4 border-[2px] border-muted rounded-full z-10",
429
+ isActive ? "bg-success-semantic" : "bg-text-tertiary"
430
430
  )}
431
431
  title={isActive ? "Hoạt động" : "Đã khóa"}
432
432
  />
433
433
  </div>
434
434
  <div>
435
- <h2 className="text-[18px] sm:text-[20px] font-semibold leading-tight text-[#0f172a] dark:text-white">
435
+ <h2 className="text-[18px] sm:text-[20px] font-semibold leading-tight text-foreground">
436
436
  {profileData.name || "Chưa đặt tên"}
437
437
  </h2>
438
- <p className="mt-1 text-[13px] text-[#64748b] dark:text-[#94a3b8]">
438
+ <p className="mt-1 text-[13px] text-muted-foreground">
439
439
  {profileData.email || profileData.phone || "Chưa có thông tin liên hệ"}
440
440
  </p>
441
441
  </div>
@@ -455,7 +455,7 @@ export function UnifiedProfileDialog({
455
455
  // dịch kèm `display:block` với độ ưu tiên (0,1,1) cao hơn `inline-flex`
456
456
  // (0,1,0) của span icon+chữ bên trong, nên icon (svg Preflight display:block)
457
457
  // bị đẩy xuống dòng riêng. `!inline-flex` (!important) thắng tuyệt đối.
458
- className="shrink-0 h-9 min-h-0 whitespace-nowrap [&_span]:!inline-flex [&_span]:!items-center [&_span]:!gap-2 [&_span]:overflow-hidden [&_svg]:shrink-0 bg-white dark:bg-[#1e293b] border-[#e2e8f0] dark:border-[#334155] focus:ring-[#1641CE] focus:border-[#1641CE] rounded-md"
458
+ className="shrink-0 h-9 min-h-0 whitespace-nowrap [&_span]:!inline-flex [&_span]:!items-center [&_span]:!gap-2 [&_span]:overflow-hidden [&_svg]:shrink-0 bg-background border-input focus:ring-primary focus:border-primary rounded-md"
459
459
  >
460
460
  <SelectValue placeholder="Chọn loại" />
461
461
  </SelectTrigger>
@@ -465,7 +465,7 @@ export function UnifiedProfileDialog({
465
465
  className="inline-flex items-center gap-2"
466
466
  style={{ whiteSpace: "nowrap" }}
467
467
  >
468
- <UserCog className="h-4 w-4 text-[#1641CE] shrink-0" />
468
+ <UserCog className="h-4 w-4 text-primary shrink-0" />
469
469
  Nhân viên
470
470
  </span>
471
471
  </SelectItem>
@@ -474,7 +474,7 @@ export function UnifiedProfileDialog({
474
474
  className="inline-flex items-center gap-2"
475
475
  style={{ whiteSpace: "nowrap" }}
476
476
  >
477
- <User className="h-4 w-4 text-[#059669] shrink-0" />
477
+ <User className="h-4 w-4 text-emerald-600 shrink-0" />
478
478
  Khách hàng
479
479
  </span>
480
480
  </SelectItem>
@@ -483,7 +483,7 @@ export function UnifiedProfileDialog({
483
483
  className="inline-flex items-center gap-2"
484
484
  style={{ whiteSpace: "nowrap" }}
485
485
  >
486
- <Store className="h-4 w-4 text-[#EA580C] shrink-0" />
486
+ <Store className="h-4 w-4 text-orange-600 shrink-0" />
487
487
  Nhà cung cấp
488
488
  </span>
489
489
  </SelectItem>
@@ -492,17 +492,17 @@ export function UnifiedProfileDialog({
492
492
  ) : (
493
493
  <div className="flex items-center gap-1.5 shrink-0">
494
494
  {userType === "employee" && (
495
- <span className="text-[12px] px-2.5 py-1 font-semibold rounded-md bg-[#1641CE]/10 text-[#1641CE] border border-[#1641CE]/20 inline-flex items-center">
495
+ <span className="text-[12px] px-2.5 py-1 font-semibold rounded-md bg-primary/10 text-primary border border-primary/20 inline-flex items-center">
496
496
  <UserCog className="h-3.5 w-3.5 mr-1.5" /> Nhân viên
497
497
  </span>
498
498
  )}
499
499
  {userType === "customer" && (
500
- <span className="text-[12px] px-2.5 py-1 font-semibold rounded-md bg-[#059669] text-white inline-flex items-center">
500
+ <span className="text-[12px] px-2.5 py-1 font-semibold rounded-md bg-emerald-600 text-white inline-flex items-center">
501
501
  <User className="h-3.5 w-3.5 mr-1.5" /> Khách hàng
502
502
  </span>
503
503
  )}
504
504
  {userType === "supplier" && (
505
- <span className="text-[12px] px-2.5 py-1 font-semibold rounded-md bg-[#EA580C] text-white inline-flex items-center">
505
+ <span className="text-[12px] px-2.5 py-1 font-semibold rounded-md bg-orange-600 text-white inline-flex items-center">
506
506
  <Store className="h-3.5 w-3.5 mr-1.5" /> Nhà cung cấp
507
507
  </span>
508
508
  )}
@@ -512,7 +512,7 @@ export function UnifiedProfileDialog({
512
512
  <Button
513
513
  variant="outline"
514
514
  onClick={() => onOpenChange(false)}
515
- className="border border-[#e2e8f0] bg-white dark:border-[#334155] text-[#475569] dark:text-white dark:bg-[#1e293b] hover:bg-[#f1f5f9] gap-2 h-9 rounded-md px-4 text-[13px] font-medium"
515
+ className="border border-border bg-background text-foreground hover:bg-accent gap-2 h-9 rounded-md px-4 text-[13px] font-medium"
516
516
  >
517
517
  <span className="hidden sm:inline">Đóng</span>
518
518
  <X className="h-4 w-4 sm:hidden" />
@@ -542,7 +542,7 @@ export function UnifiedProfileDialog({
542
542
  "relative pb-3 text-[14px] font-medium transition-all whitespace-nowrap flex items-center gap-2",
543
543
  activeSection === item.id
544
544
  ? "text-primary dark:text-primary"
545
- : "text-[#64748b] hover:text-[#0f172a] dark:text-[#94a3b8] dark:hover:text-white"
545
+ : "text-muted-foreground hover:text-foreground"
546
546
  )}
547
547
  >
548
548
  <item.icon
@@ -550,7 +550,7 @@ export function UnifiedProfileDialog({
550
550
  "h-[16px] w-[16px]",
551
551
  activeSection === item.id
552
552
  ? "text-primary dark:text-primary"
553
- : "text-[#94a3b8]"
553
+ : "text-muted-foreground"
554
554
  )}
555
555
  strokeWidth={2}
556
556
  />
@@ -564,7 +564,7 @@ export function UnifiedProfileDialog({
564
564
  </div>
565
565
 
566
566
  {/* MAIN CONTENT AREA */}
567
- <div className="flex-1 bg-white dark:bg-[#0f172a] overflow-y-auto overscroll-contain touch-pan-y" style={{ WebkitOverflowScrolling: 'touch' }}>
567
+ <div className="flex-1 bg-background overflow-y-auto overscroll-contain touch-pan-y" style={{ WebkitOverflowScrolling: 'touch' }}>
568
568
  <div className="p-4 sm:p-5 max-w-4xl mx-auto space-y-4 pb-20">
569
569
  {/* General Section */}
570
570
  {activeSection === "general" && (
@@ -572,8 +572,8 @@ export function UnifiedProfileDialog({
572
572
 
573
573
  <div className="grid md:grid-cols-2 gap-x-6 gap-y-4">
574
574
  <div className="space-y-1.5">
575
- <Label className="text-[13px] font-medium text-[#334155] dark:text-[#cbd5e1]">
576
- Họ và tên <span className="text-[#e41e3f]">*</span>
575
+ <Label className="text-[13px] font-medium text-foreground">
576
+ Họ và tên <span className="text-destructive">*</span>
577
577
  </Label>
578
578
  <Input
579
579
  value={profileData.name}
@@ -584,11 +584,11 @@ export function UnifiedProfileDialog({
584
584
  })
585
585
  }
586
586
  placeholder="Nguyễn Văn A"
587
- className="bg-white dark:bg-[#1e293b] border-[#e2e8f0] dark:border-[#334155] focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
587
+ className="bg-background border-input focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
588
588
  />
589
589
  </div>
590
590
  <div className="space-y-1.5">
591
- <Label className="text-[13px] font-medium text-[#334155] dark:text-[#cbd5e1]">Email</Label>
591
+ <Label className="text-[13px] font-medium text-foreground">Email</Label>
592
592
  <Input
593
593
  value={profileData.email}
594
594
  onChange={(e) =>
@@ -598,11 +598,11 @@ export function UnifiedProfileDialog({
598
598
  })
599
599
  }
600
600
  placeholder="email@example.com"
601
- className="bg-white dark:bg-[#1e293b] border-[#e2e8f0] dark:border-[#334155] focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
601
+ className="bg-background border-input focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
602
602
  />
603
603
  </div>
604
604
  <div className="space-y-1.5">
605
- <Label className="text-[13px] font-medium text-[#334155] dark:text-[#cbd5e1]">Số điện thoại</Label>
605
+ <Label className="text-[13px] font-medium text-foreground">Số điện thoại</Label>
606
606
  <Input
607
607
  value={profileData.phone}
608
608
  onChange={(e) =>
@@ -612,11 +612,11 @@ export function UnifiedProfileDialog({
612
612
  })
613
613
  }
614
614
  placeholder="0912..."
615
- className="bg-white dark:bg-[#1e293b] border-[#e2e8f0] dark:border-[#334155] focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
615
+ className="bg-background border-input focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
616
616
  />
617
617
  </div>
618
618
  <div className="space-y-1.5">
619
- <Label className="text-[13px] font-medium text-[#334155] dark:text-[#cbd5e1]">Địa chỉ</Label>
619
+ <Label className="text-[13px] font-medium text-foreground">Địa chỉ</Label>
620
620
  <Input
621
621
  value={profileData.address}
622
622
  onChange={(e) =>
@@ -626,14 +626,14 @@ export function UnifiedProfileDialog({
626
626
  })
627
627
  }
628
628
  placeholder="Số nhà, đường..."
629
- className="bg-white dark:bg-[#1e293b] border-[#e2e8f0] dark:border-[#334155] focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
629
+ className="bg-background border-input focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
630
630
  />
631
631
  </div>
632
632
  {/* Status Toggle */}
633
633
  {viewMode === "admin" && (
634
634
  <div className="space-y-1.5">
635
- <Label className="text-[13px] font-medium text-[#334155] dark:text-[#cbd5e1]">Trạng thái</Label>
636
- <div className="flex items-center gap-3 h-9 px-3 rounded-[6px] border border-[#ced0d4] dark:border-[#333840] bg-[#ffffff] dark:bg-[#0a1317]">
635
+ <Label className="text-[13px] font-medium text-foreground">Trạng thái</Label>
636
+ <div className="flex items-center gap-3 h-9 px-3 rounded-[6px] border border-input bg-background">
637
637
  <Switch
638
638
  id="user-active-switch"
639
639
  checked={isActive}
@@ -647,7 +647,7 @@ export function UnifiedProfileDialog({
647
647
  <span
648
648
  className={cn(
649
649
  "text-[13px] font-bold tracking-[-0.13px]",
650
- isActive ? "text-[#31a24c]" : "text-[#444950]",
650
+ isActive ? "text-success-text" : "text-muted-foreground",
651
651
  )}
652
652
  >
653
653
  {isActive ? "Hoạt động" : "Đã khóa"}
@@ -657,7 +657,7 @@ export function UnifiedProfileDialog({
657
657
  )}
658
658
  {/* Additional Info for All */}
659
659
  <div className="space-y-1.5">
660
- <Label className="text-[13px] font-medium text-[#334155] dark:text-[#cbd5e1]">Ngày sinh</Label>
660
+ <Label className="text-[13px] font-medium text-foreground">Ngày sinh</Label>
661
661
  <DatePicker
662
662
  value={ymdToDate(profileData.birthday)}
663
663
  onValueChange={(d) =>
@@ -668,18 +668,18 @@ export function UnifiedProfileDialog({
668
668
  }
669
669
  formatStr="dd/MM/yyyy"
670
670
  placeholder="dd/mm/yyyy"
671
- buttonClassName="bg-white dark:bg-[#1e293b] border-[#e2e8f0] dark:border-[#334155] focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
671
+ buttonClassName="bg-background border-input focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
672
672
  />
673
673
  </div>
674
674
  <div className="space-y-1.5">
675
- <Label className="text-[13px] font-medium text-[#334155] dark:text-[#cbd5e1]">Giới tính</Label>
675
+ <Label className="text-[13px] font-medium text-foreground">Giới tính</Label>
676
676
  <Select
677
677
  value={profileData.gender}
678
678
  onValueChange={(val) =>
679
679
  setProfileData({ ...profileData, gender: val })
680
680
  }
681
681
  >
682
- <SelectTrigger className="bg-white dark:bg-[#1e293b] border-[#e2e8f0] dark:border-[#334155] focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]">
682
+ <SelectTrigger className="bg-background border-input focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]">
683
683
  <SelectValue placeholder="Chọn giới tính" />
684
684
  </SelectTrigger>
685
685
  <SelectContent>
@@ -690,7 +690,7 @@ export function UnifiedProfileDialog({
690
690
  </Select>
691
691
  </div>
692
692
  <div className="space-y-1.5">
693
- <Label className="text-[13px] font-medium text-[#334155] dark:text-[#cbd5e1]">CCCD/CMND</Label>
693
+ <Label className="text-[13px] font-medium text-foreground">CCCD/CMND</Label>
694
694
  <Input
695
695
  value={profileData.idNumber}
696
696
  onChange={(e) =>
@@ -699,14 +699,14 @@ export function UnifiedProfileDialog({
699
699
  idNumber: e.target.value,
700
700
  })
701
701
  }
702
- className="bg-white dark:bg-[#1e293b] border-[#e2e8f0] dark:border-[#334155] focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
702
+ className="bg-background border-input focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]"
703
703
  />
704
704
  </div>
705
705
 
706
706
  {/* Customer Specific */}
707
707
  {isCustomer && (
708
708
  <div className="space-y-1.5">
709
- <Label className="text-[13px] font-medium text-[#334155] dark:text-[#cbd5e1]">
709
+ <Label className="text-[13px] font-medium text-foreground">
710
710
  Nhóm khách hàng
711
711
  </Label>
712
712
  <Select
@@ -715,7 +715,7 @@ export function UnifiedProfileDialog({
715
715
  setProfileData({ ...profileData, groupId: val })
716
716
  }
717
717
  >
718
- <SelectTrigger className="bg-white dark:bg-[#1e293b] border-[#e2e8f0] dark:border-[#334155] focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]">
718
+ <SelectTrigger className="bg-background border-input focus:ring-primary focus:border-primary rounded-md h-9 text-[13px]">
719
719
  <SelectValue placeholder="Chọn nhóm" />
720
720
  </SelectTrigger>
721
721
  <SelectContent>
@@ -732,8 +732,8 @@ export function UnifiedProfileDialog({
732
732
 
733
733
  {isCustomer && (
734
734
  <div className="pt-4">
735
- <div className="flex items-center justify-between mb-4 border-b border-[#dee3e9] pb-2">
736
- <h3 className="text-[18px] font-bold tracking-[-0.14px] text-[#0a1317] dark:text-white">
735
+ <div className="flex items-center justify-between mb-4 border-b border-border pb-2">
736
+ <h3 className="text-[18px] font-bold tracking-[-0.14px] text-foreground">
737
737
  Tài khoản đăng nhập
738
738
  </h3>
739
739
  <Switch
@@ -746,7 +746,7 @@ export function UnifiedProfileDialog({
746
746
  <div className="space-y-4 animate-in fade-in slide-in-from-top-2">
747
747
  <div className="grid md:grid-cols-2 gap-x-6 gap-y-4">
748
748
  <div className="space-y-1.5 col-span-2 md:col-span-1">
749
- <Label className="text-[13px] font-medium text-[#334155] dark:text-[#cbd5e1]">
749
+ <Label className="text-[13px] font-medium text-foreground">
750
750
  Mật khẩu
751
751
  </Label>
752
752
  <div className="relative">
@@ -760,13 +760,13 @@ export function UnifiedProfileDialog({
760
760
  }))
761
761
  }
762
762
  placeholder="Nhập mật khẩu"
763
- className="pr-10 bg-[#ffffff] dark:bg-[#0a1317] border-[#ced0d4] dark:border-[#333840] focus:ring-[#0064e0] focus:border-[#0064e0] rounded-[6px] h-9 text-[14px]"
763
+ className="pr-10 bg-background border-input focus:ring-primary focus:border-primary rounded-[6px] h-9 text-[14px]"
764
764
  />
765
765
  <Button
766
766
  type="button"
767
767
  variant="ghost"
768
768
  size="icon"
769
- className="absolute right-0 top-0 h-full w-9 text-[#444950] hover:text-[#0a1317]"
769
+ className="absolute right-0 top-0 h-full w-9 text-muted-foreground hover:text-foreground"
770
770
  onClick={() =>
771
771
  setShowPassword(!showPassword)
772
772
  }
@@ -778,10 +778,10 @@ export function UnifiedProfileDialog({
778
778
  )}
779
779
  </Button>
780
780
  </div>
781
- <p className="text-[12px] text-[#444950] mt-1.5 flex items-center gap-1.5">
782
- <span className="inline-block w-1.5 h-1.5 rounded-full bg-[#0064e0]" />
781
+ <p className="text-[12px] text-muted-foreground mt-1.5 flex items-center gap-1.5">
782
+ <span className="inline-block w-1.5 h-1.5 rounded-full bg-primary" />
783
783
  Mặc định:{" "}
784
- <span className="font-mono font-bold text-[#1c1e21] dark:text-white">
784
+ <span className="font-mono font-bold text-foreground">
785
785
  Goeat@123456
786
786
  </span>
787
787
  </p>
@@ -789,7 +789,7 @@ export function UnifiedProfileDialog({
789
789
  </div>
790
790
 
791
791
  <div className="space-y-2 pt-2">
792
- <Label className="text-[13px] font-medium text-[#334155] dark:text-[#cbd5e1]">
792
+ <Label className="text-[13px] font-medium text-foreground">
793
793
  Phân quyền
794
794
  </Label>
795
795
  <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
@@ -801,10 +801,10 @@ export function UnifiedProfileDialog({
801
801
  <div
802
802
  key={role.code}
803
803
  className={cn(
804
- "flex items-start gap-3 p-3 rounded-md border cursor-pointer hover:bg-slate-50 transition-colors",
804
+ "flex items-start gap-3 p-3 rounded-md border cursor-pointer hover:bg-accent/50 transition-colors",
805
805
  isSelected
806
- ? "border-blue-500 bg-blue-50/50"
807
- : "bg-background border-slate-200 dark:border-slate-800",
806
+ ? "border-primary bg-primary/5"
807
+ : "bg-background border-border",
808
808
  )}
809
809
  onClick={() => {
810
810
  setSelectedRoles((prev) =>
@@ -818,10 +818,10 @@ export function UnifiedProfileDialog({
818
818
  >
819
819
  <Checkbox
820
820
  checked={isSelected}
821
- className="mt-1 data-[state=checked]:bg-blue-600 data-[state=checked]:border-blue-600"
821
+ className="mt-1 data-[state=checked]:bg-primary data-[state=checked]:border-primary"
822
822
  />
823
823
  <div className="space-y-0.5">
824
- <p className="text-sm font-medium text-slate-900 dark:text-slate-100">
824
+ <p className="text-sm font-medium text-foreground">
825
825
  {role.name}
826
826
  </p>
827
827
  <p className="text-xs text-muted-foreground line-clamp-1">
@@ -845,7 +845,7 @@ export function UnifiedProfileDialog({
845
845
  <div className="space-y-4 animate-in fade-in zoom-in-95 duration-200">
846
846
  <div className="grid md:grid-cols-2 gap-x-8 gap-y-6">
847
847
  <div className="space-y-2">
848
- <Label className="text-[13px] font-medium text-[#41454d] dark:text-[#9297a0]">Phòng ban</Label>
848
+ <Label className="text-[13px] font-medium text-foreground">Phòng ban</Label>
849
849
  <Select
850
850
  value={profileData.departmentId}
851
851
  onValueChange={(val) =>
@@ -855,7 +855,7 @@ export function UnifiedProfileDialog({
855
855
  })
856
856
  }
857
857
  >
858
- <SelectTrigger className="bg-[#ffffff] dark:bg-[#181d26] border-[#dddddd] dark:border-[#333840] focus:ring-[#458fff] focus:border-[#458fff] shadow-sm rounded-[6px]">
858
+ <SelectTrigger className="bg-background border-input focus:ring-primary focus:border-primary shadow-sm rounded-[6px]">
859
859
  <SelectValue placeholder="Chọn phòng ban" />
860
860
  </SelectTrigger>
861
861
  <SelectContent>
@@ -868,14 +868,14 @@ export function UnifiedProfileDialog({
868
868
  </Select>
869
869
  </div>
870
870
  <div className="space-y-2">
871
- <Label className="text-[13px] font-medium text-[#41454d] dark:text-[#9297a0]">Chức danh</Label>
871
+ <Label className="text-[13px] font-medium text-foreground">Chức danh</Label>
872
872
  <Select
873
873
  value={profileData.jobTitleId}
874
874
  onValueChange={(val) =>
875
875
  setProfileData({ ...profileData, jobTitleId: val })
876
876
  }
877
877
  >
878
- <SelectTrigger className="bg-[#ffffff] dark:bg-[#181d26] border-[#dddddd] dark:border-[#333840] focus:ring-[#458fff] focus:border-[#458fff] shadow-sm rounded-[6px]">
878
+ <SelectTrigger className="bg-background border-input focus:ring-primary focus:border-primary shadow-sm rounded-[6px]">
879
879
  <SelectValue placeholder="Chọn chức danh" />
880
880
  </SelectTrigger>
881
881
  <SelectContent>
@@ -889,8 +889,8 @@ export function UnifiedProfileDialog({
889
889
  </div>
890
890
  <div className="col-span-2 space-y-3 pt-2">
891
891
  <div className="flex items-center justify-between gap-3 flex-wrap">
892
- <Label className="text-[13px] font-medium text-[#41454d] dark:text-[#9297a0]">Chi nhánh làm việc</Label>
893
- <span className="inline-flex items-center gap-1 text-[12px] text-[#94a3b8]">
892
+ <Label className="text-[13px] font-medium text-foreground">Chi nhánh làm việc</Label>
893
+ <span className="inline-flex items-center gap-1 text-[12px] text-muted-foreground">
894
894
  <Star className="h-3 w-3" />
895
895
  Đánh dấu một chi nhánh mặc định
896
896
  </span>
@@ -904,23 +904,23 @@ export function UnifiedProfileDialog({
904
904
  <div
905
905
  key={branch.id}
906
906
  className={cn(
907
- "flex items-center gap-3 p-3 rounded-md border cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-800/40 transition-colors",
907
+ "flex items-center gap-3 p-3 rounded-md border cursor-pointer hover:bg-accent/50 transition-colors",
908
908
  isSelected
909
- ? "border-blue-500 bg-blue-50/50 dark:bg-blue-500/10"
910
- : "bg-background border-slate-200 dark:border-slate-800",
909
+ ? "border-primary bg-primary/5"
910
+ : "bg-background border-border",
911
911
  )}
912
912
  onClick={() => toggleBranch(branch.id)}
913
913
  >
914
914
  <Checkbox
915
915
  checked={isSelected}
916
- className="data-[state=checked]:bg-blue-600 data-[state=checked]:border-blue-600"
916
+ className="data-[state=checked]:bg-primary data-[state=checked]:border-primary"
917
917
  />
918
- <span className="flex-1 text-sm font-medium text-slate-900 dark:text-slate-100">
918
+ <span className="flex-1 text-sm font-medium text-foreground">
919
919
  {branch.name}
920
920
  </span>
921
921
  {isSelected &&
922
922
  (isDefault ? (
923
- <span className="inline-flex items-center gap-1 rounded-full bg-blue-600 px-2 py-0.5 text-[11px] font-semibold text-white shrink-0">
923
+ <span className="inline-flex items-center gap-1 rounded-full bg-primary px-2 py-0.5 text-[11px] font-semibold text-primary-foreground shrink-0">
924
924
  <Star className="h-3 w-3 fill-current" />
925
925
  Mặc định
926
926
  </span>
@@ -932,7 +932,7 @@ export function UnifiedProfileDialog({
932
932
  markDefaultBranch(branch.id);
933
933
  }}
934
934
  title="Đặt làm chi nhánh mặc định"
935
- className="inline-flex items-center gap-1 rounded-full border border-slate-200 dark:border-slate-700 px-2 py-0.5 text-[11px] font-medium text-slate-500 dark:text-slate-400 hover:border-blue-400 hover:text-blue-600 transition-colors shrink-0"
935
+ className="inline-flex items-center gap-1 rounded-full border border-border px-2 py-0.5 text-[11px] font-medium text-muted-foreground hover:border-primary/50 hover:text-primary transition-colors shrink-0"
936
936
  >
937
937
  <Star className="h-3 w-3" />
938
938
  Đặt mặc định
@@ -951,7 +951,7 @@ export function UnifiedProfileDialog({
951
951
  <div className="space-y-4 animate-in fade-in zoom-in-95 duration-200">
952
952
  <div className="max-w-2xl space-y-6">
953
953
  <div className="space-y-2">
954
- <Label className="text-[13px] font-medium text-[#41454d] dark:text-[#9297a0]">
954
+ <Label className="text-[13px] font-medium text-foreground">
955
955
  Chọn nhà cung cấp
956
956
  </Label>
957
957
  <Select
@@ -960,7 +960,7 @@ export function UnifiedProfileDialog({
960
960
  setProfileData({ ...profileData, supplierId: val })
961
961
  }
962
962
  >
963
- <SelectTrigger className="bg-[#ffffff] dark:bg-[#181d26] border-[#dddddd] dark:border-[#333840] focus:ring-[#458fff] focus:border-[#458fff] shadow-sm rounded-[6px]">
963
+ <SelectTrigger className="bg-background border-input focus:ring-primary focus:border-primary shadow-sm rounded-[6px]">
964
964
  <SelectValue placeholder="Chọn nhà cung cấp" />
965
965
  </SelectTrigger>
966
966
  <SelectContent>
@@ -972,7 +972,7 @@ export function UnifiedProfileDialog({
972
972
  </SelectContent>
973
973
  </Select>
974
974
  </div>
975
- <div className="rounded-md bg-blue-50 p-4 text-sm text-blue-700 flex items-start gap-3">
975
+ <div className="rounded-md bg-info-subtle p-4 text-sm text-info-text flex items-start gap-3">
976
976
  <Store className="h-5 w-5 mt-0.5 shrink-0" />
977
977
  <p>
978
978
  Tài khoản này sẽ được liên kết với nhà cung cấp đã
@@ -986,14 +986,14 @@ export function UnifiedProfileDialog({
986
986
 
987
987
  {activeSection === "roles" && (
988
988
  <div className="animate-in fade-in zoom-in-95 duration-200">
989
- <div className="sticky -top-4 sm:-top-5 pt-2 sm:pt-2 pb-4 -mx-4 sm:-mx-5 px-4 sm:px-5 bg-white/95 dark:bg-[#0f172a]/95 backdrop-blur-sm z-10 border-b border-[#e2e8f0] dark:border-[#334155] mb-4 shadow-sm">
989
+ <div className="sticky -top-4 sm:-top-5 pt-2 sm:pt-2 pb-4 -mx-4 sm:-mx-5 px-4 sm:px-5 bg-background/95 backdrop-blur-sm z-10 border-b border-border mb-4 shadow-sm">
990
990
  <div className="relative max-w-md">
991
- <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-[#64748b]" />
991
+ <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
992
992
  <Input
993
993
  placeholder="Tìm kiếm vai trò..."
994
994
  value={roleSearchQuery}
995
995
  onChange={(e) => setRoleSearchQuery(e.target.value)}
996
- className="pl-9 bg-white dark:bg-[#1e293b] border-[#e2e8f0] dark:border-[#334155] focus:ring-primary focus:border-primary shadow-sm rounded-md h-9 text-[13px]"
996
+ className="pl-9 bg-background border-input focus:ring-primary focus:border-primary shadow-sm rounded-md h-9 text-[13px]"
997
997
  />
998
998
  </div>
999
999
  </div>
@@ -1005,10 +1005,10 @@ export function UnifiedProfileDialog({
1005
1005
  <div
1006
1006
  key={role.code}
1007
1007
  className={cn(
1008
- "flex items-start gap-3 p-3 rounded-md border cursor-pointer hover:bg-slate-50 transition-colors",
1008
+ "flex items-start gap-3 p-3 rounded-md border cursor-pointer hover:bg-accent/50 transition-colors",
1009
1009
  isSelected
1010
- ? "border-blue-500 bg-blue-50/50"
1011
- : "bg-background border-slate-200 dark:border-slate-800",
1010
+ ? "border-primary bg-primary/5"
1011
+ : "bg-background border-border",
1012
1012
  )}
1013
1013
  onClick={() => {
1014
1014
  setSelectedRoles((prev) =>
@@ -1020,10 +1020,10 @@ export function UnifiedProfileDialog({
1020
1020
  >
1021
1021
  <Checkbox
1022
1022
  checked={isSelected}
1023
- className="mt-1 data-[state=checked]:bg-blue-600 data-[state=checked]:border-blue-600"
1023
+ className="mt-1 data-[state=checked]:bg-primary data-[state=checked]:border-primary"
1024
1024
  />
1025
1025
  <div className="space-y-0.5">
1026
- <p className="text-sm font-medium text-slate-900 dark:text-slate-100">
1026
+ <p className="text-sm font-medium text-foreground">
1027
1027
  {role.name}
1028
1028
  </p>
1029
1029
  <p className="text-xs text-muted-foreground line-clamp-1">
@@ -1049,7 +1049,7 @@ export function UnifiedProfileDialog({
1049
1049
  </div>
1050
1050
  <div className="grid md:grid-cols-2 gap-x-8 gap-y-6">
1051
1051
  <div className="space-y-2">
1052
- <Label className="text-[13px] font-medium text-[#41454d] dark:text-[#9297a0]">Mật khẩu mới</Label>
1052
+ <Label className="text-[13px] font-medium text-foreground">Mật khẩu mới</Label>
1053
1053
  <div className="relative">
1054
1054
  <Input
1055
1055
  type={showPassword ? "text" : "password"}
@@ -1060,7 +1060,7 @@ export function UnifiedProfileDialog({
1060
1060
  password: e.target.value,
1061
1061
  }))
1062
1062
  }
1063
- className="pr-10 bg-[#ffffff] dark:bg-[#181d26] border-[#dddddd] dark:border-[#333840] focus:ring-[#458fff] focus:border-[#458fff] shadow-sm rounded-[6px]"
1063
+ className="pr-10 bg-background border-input focus:ring-primary focus:border-primary shadow-sm rounded-[6px]"
1064
1064
  />
1065
1065
  <Button
1066
1066
  type="button"
@@ -1078,7 +1078,7 @@ export function UnifiedProfileDialog({
1078
1078
  </div>
1079
1079
  </div>
1080
1080
  <div className="space-y-2">
1081
- <Label className="text-[13px] font-medium text-[#41454d] dark:text-[#9297a0]">
1081
+ <Label className="text-[13px] font-medium text-foreground">
1082
1082
  Xác nhận mật khẩu
1083
1083
  </Label>
1084
1084
  <Input
@@ -1090,7 +1090,7 @@ export function UnifiedProfileDialog({
1090
1090
  confirm: e.target.value,
1091
1091
  }))
1092
1092
  }
1093
- className="bg-[#ffffff] dark:bg-[#181d26] border-[#dddddd] dark:border-[#333840] focus:ring-[#458fff] focus:border-[#458fff] shadow-sm rounded-[6px]"
1093
+ className="bg-background border-input focus:ring-primary focus:border-primary shadow-sm rounded-[6px]"
1094
1094
  />
1095
1095
  </div>
1096
1096
  </div>