@goplusvn/core 0.1.62 → 0.1.63

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@goplusvn/core",
3
3
  "description": "GoPlusVN Platform Kit - ERP kernel: layout, RBAC, CRUD, multi-tenant, system pages",
4
- "version": "0.1.62",
4
+ "version": "0.1.63",
5
5
  "private": false,
6
6
  "publishConfig": {
7
7
  "registry": "https://registry.npmjs.org",
@@ -137,8 +137,8 @@ export function CrudExportButton({
137
137
  className="rounded-r-none border-r-0"
138
138
  onClick={() => handleExport("current")}
139
139
  >
140
- <Download className="mr-2 h-4 w-4" />
141
- {loading ? "Exporting..." : "Export"}
140
+ <Download className="h-4 w-4 sm:mr-2" />
141
+ <span className="hidden sm:inline">{loading ? "Exporting..." : "Export"}</span>
142
142
  </Button>
143
143
  <DropdownMenu>
144
144
  <DropdownMenuTrigger asChild>
@@ -368,8 +368,8 @@ export function ImportDialog({
368
368
  <DialogTrigger asChild>
369
369
  {trigger ?? (
370
370
  <Button variant="outline" size="sm">
371
- <Upload className="mr-2 h-4 w-4" />
372
- Import
371
+ <Upload className="h-4 w-4 sm:mr-2" />
372
+ <span className="hidden sm:inline">Import</span>
373
373
  </Button>
374
374
  )}
375
375
  </DialogTrigger>
@@ -48,89 +48,99 @@ export function UserToolbar({
48
48
  }, [localSearch, onSearchChange]);
49
49
 
50
50
  return (
51
- <div className="flex items-center gap-2 flex-wrap">
52
- <div className="relative">
53
- <Search className="absolute left-3 top-2.5 h-4 w-4 text-muted-foreground" />
54
- <Input
55
- placeholder="Tìm người dùng..."
56
- value={localSearch}
57
- onChange={(e) => setLocalSearch(e.target.value)}
58
- className="h-9 w-[220px] lg:w-[280px] pl-9 text-xs bg-background border hover:bg-muted/50 transition-colors shadow-sm rounded-md focus-visible:ring-1 focus-visible:ring-primary"
59
- />
60
- {localSearch && (
61
- <Button
62
- variant="ghost"
63
- size="sm"
64
- className="absolute right-1 top-1/2 -translate-y-1/2 h-7 w-7 p-0 rounded-md hover:bg-muted"
65
- onClick={() => setLocalSearch("")}
66
- >
67
- <X className="h-3.5 w-3.5" />
68
- </Button>
69
- )}
70
- </div>
71
-
72
- <Select value={userType} onValueChange={onUserTypeChange}>
73
- <SelectTrigger className="h-9 w-[150px] text-xs bg-background border hover:bg-muted/50 transition-colors shadow-sm rounded-md focus-visible:ring-primary">
74
- <SelectValue placeholder="Loại tài khoản" />
75
- </SelectTrigger>
76
- <SelectContent className="rounded-lg">
77
- <SelectItem value="all">Tất cả loại</SelectItem>
78
- <SelectItem value="employee">Nhân viên</SelectItem>
79
- <SelectItem value="customer">Khách hàng</SelectItem>
80
- <SelectItem value="supplier">Nhà cung cấp</SelectItem>
81
- </SelectContent>
82
- </Select>
51
+ <div className="flex flex-col xl:flex-row items-start xl:items-center justify-between w-full gap-3 xl:gap-4">
52
+ {/* Tìm kiếm + bộ lọc chính */}
53
+ <div className="flex w-full min-w-0 xl:w-auto flex-1 items-center gap-2 xl:gap-3">
54
+ <div className="relative w-full xl:flex-[2] xl:min-w-[220px] max-w-none">
55
+ <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
56
+ <Input
57
+ placeholder="Tìm người dùng..."
58
+ value={localSearch}
59
+ onChange={(e) => setLocalSearch(e.target.value)}
60
+ className="pl-9 h-9 w-full text-xs bg-secondary/30 border hover:bg-muted/50 transition-colors shadow-sm rounded-md focus-visible:ring-1 focus-visible:ring-primary"
61
+ />
62
+ {localSearch && (
63
+ <Button
64
+ variant="ghost"
65
+ size="sm"
66
+ className="absolute right-1 top-1/2 -translate-y-1/2 h-7 w-7 p-0 rounded-md hover:bg-muted"
67
+ onClick={() => setLocalSearch("")}
68
+ >
69
+ <X className="h-3.5 w-3.5" />
70
+ </Button>
71
+ )}
72
+ </div>
83
73
 
84
- <Select onValueChange={onRoleChange}>
85
- <SelectTrigger className="h-9 w-[170px] text-xs bg-background border hover:bg-muted/50 transition-colors shadow-sm rounded-md focus-visible:ring-primary">
86
- <SelectValue placeholder="Lọc theo vai trò" />
87
- </SelectTrigger>
88
- <SelectContent className="rounded-lg">
89
- <SelectItem value="all">Tất cả vai trò</SelectItem>
90
- {roles?.map((role) => (
91
- <SelectItem key={role.code} value={role.code}>
92
- {role.name}
93
- </SelectItem>
94
- ))}
95
- </SelectContent>
96
- </Select>
74
+ <div className="w-full xl:w-auto flex-1 min-w-0">
75
+ <Select value={userType} onValueChange={onUserTypeChange}>
76
+ <SelectTrigger className="h-9 w-full xl:w-[150px] text-xs bg-background border hover:bg-muted/50 transition-colors shadow-sm rounded-md focus-visible:ring-primary min-w-0">
77
+ <SelectValue placeholder="Loại tài khoản" className="truncate" />
78
+ </SelectTrigger>
79
+ <SelectContent className="rounded-lg">
80
+ <SelectItem value="all">Tất cả loại</SelectItem>
81
+ <SelectItem value="employee">Nhân viên</SelectItem>
82
+ <SelectItem value="customer">Khách hàng</SelectItem>
83
+ <SelectItem value="supplier">Nhà cung cấp</SelectItem>
84
+ </SelectContent>
85
+ </Select>
86
+ </div>
97
87
 
98
- <div className="ml-auto flex items-center gap-2">
99
- <div className="flex items-center bg-[#f1f5f9] dark:bg-[#181d26] rounded-[6px] p-0.5 border border-[#dddddd] dark:border-[#333840]">
100
- <Button
101
- variant={viewMode === "table" ? "secondary" : "ghost"}
102
- size="sm"
103
- className="h-8 w-8 p-0 rounded-md"
104
- onClick={() => onViewModeChange("table")}
105
- >
106
- <List className="h-4 w-4" />
107
- </Button>
108
- <Button
109
- variant={viewMode === "grid" ? "secondary" : "ghost"}
110
- size="sm"
111
- className="h-8 w-8 p-0 rounded-md"
112
- onClick={() => onViewModeChange("grid")}
113
- >
114
- <LayoutGrid className="h-4 w-4" />
115
- </Button>
88
+ <div className="w-full xl:w-auto flex-1 min-w-0">
89
+ <Select onValueChange={onRoleChange}>
90
+ <SelectTrigger className="h-9 w-full xl:w-[170px] text-xs bg-background border hover:bg-muted/50 transition-colors shadow-sm rounded-md focus-visible:ring-primary min-w-0">
91
+ <SelectValue placeholder="Lọc theo vai trò" className="truncate" />
92
+ </SelectTrigger>
93
+ <SelectContent className="rounded-lg">
94
+ <SelectItem value="all">Tất cả vai trò</SelectItem>
95
+ {roles?.map((role) => (
96
+ <SelectItem key={role.code} value={role.code}>
97
+ {role.name}
98
+ </SelectItem>
99
+ ))}
100
+ </SelectContent>
101
+ </Select>
116
102
  </div>
103
+ </div>
117
104
 
118
- {permissions.export && (
119
- <div className="[&>button]:h-9 [&>button]:rounded-md [&>button]:shadow-sm [&>button]:bg-background [&>button]:border [&>button]:text-foreground [&>button]:hover:bg-muted/50">
120
- <CrudExportButton
121
- endpoint="/api/crud/users/export"
122
- search={localSearch}
123
- canExport={true}
124
- />
105
+ {/* Hành động */}
106
+ <div className="flex items-center justify-between sm:justify-end gap-2 w-full xl:w-auto shrink-0 overflow-x-auto pb-0.5 sm:pb-0">
107
+ <div className="flex items-center gap-2">
108
+ <div className="flex items-center bg-[#f1f5f9] dark:bg-[#181d26] rounded-[6px] p-0.5 border border-[#dddddd] dark:border-[#333840] shrink-0">
109
+ <Button
110
+ variant={viewMode === "table" ? "secondary" : "ghost"}
111
+ size="sm"
112
+ className="h-8 w-8 p-0 rounded-md"
113
+ onClick={() => onViewModeChange("table")}
114
+ >
115
+ <List className="h-4 w-4" />
116
+ </Button>
117
+ <Button
118
+ variant={viewMode === "grid" ? "secondary" : "ghost"}
119
+ size="sm"
120
+ className="h-8 w-8 p-0 rounded-md"
121
+ onClick={() => onViewModeChange("grid")}
122
+ >
123
+ <LayoutGrid className="h-4 w-4" />
124
+ </Button>
125
125
  </div>
126
- )}
127
126
 
128
- {permissions.create && (
129
- <Button size="sm" className="h-9 px-4 text-xs bg-primary hover:bg-primary/90 text-primary-foreground shadow-sm rounded-md font-medium border-0" onClick={onCreateNew}>
130
- <Plus className="h-4 w-4 mr-1.5" />
131
- Thêm mới
132
- </Button>
133
- )}
127
+ {permissions.export && (
128
+ <div className="[&>button]:h-9 [&>button]:rounded-md [&>button]:shadow-sm [&>button]:bg-background [&>button]:border [&>button]:text-foreground [&>button]:hover:bg-muted/50 shrink-0">
129
+ <CrudExportButton
130
+ endpoint="/api/crud/users/export"
131
+ search={localSearch}
132
+ canExport={true}
133
+ />
134
+ </div>
135
+ )}
136
+
137
+ {permissions.create && (
138
+ <Button size="sm" className="h-9 px-4 text-xs bg-primary hover:bg-primary/90 text-primary-foreground shadow-sm rounded-md font-medium border-0 shrink-0" onClick={onCreateNew}>
139
+ <Plus className="h-4 w-4 sm:mr-1.5" />
140
+ <span className="hidden sm:inline">Thêm mới</span>
141
+ </Button>
142
+ )}
143
+ </div>
134
144
  </div>
135
145
  </div>
136
146
  );