beautify: modal registered user component

This commit is contained in:
DeathKaioken 2025-10-22 20:28:02 +02:00
parent 6fa4f02fb2
commit 9f5da2c43d

View File

@ -4,7 +4,7 @@ import React, { useMemo, useState } from 'react'
import { UsersIcon } from '@heroicons/react/24/outline' import { UsersIcon } from '@heroicons/react/24/outline'
type UserType = 'personal' | 'company' type UserType = 'personal' | 'company'
type UserStatus = 'active' | 'pending' | 'blocked' type UserStatus = 'active' | 'inactive' | 'pending' | 'blocked' // CHANGED: add inactive
export interface RegisteredUser { export interface RegisteredUser {
id: string | number id: string | number
@ -64,6 +64,7 @@ const allDummyUsers = buildDummyAll()
function statusBadgeClass(s: UserStatus) { function statusBadgeClass(s: UserStatus) {
switch (s) { switch (s) {
case 'active': return 'bg-green-100 text-green-800' case 'active': return 'bg-green-100 text-green-800'
case 'inactive': return 'bg-gray-100 text-gray-800' // NEW
case 'pending': return 'bg-amber-100 text-amber-800' case 'pending': return 'bg-amber-100 text-amber-800'
case 'blocked': return 'bg-rose-100 text-rose-800' case 'blocked': return 'bg-rose-100 text-rose-800'
default: return 'bg-slate-100 text-slate-800' default: return 'bg-slate-100 text-slate-800'
@ -98,17 +99,28 @@ function exportCsv(rows: RegisteredUser[]) {
} }
export default function RegisteredUserList({ users, loading }: Props) { export default function RegisteredUserList({ users, loading }: Props) {
// Main widget rows (latest 5) // Normalize backend shape to local RegisteredUser shape (type/status/registeredAt)
const sorted = useMemo(() => { const normalizedUsers = useMemo<RegisteredUser[]>(() => {
const data = (users && users.length > 0 ? users : baseUsers).slice() if (!users || users.length === 0) return []
return data.sort((a, b) => new Date(b.registeredAt).getTime() - new Date(a.registeredAt).getTime()) return users.map((u: any) => ({
...u,
userType: u.userType ?? u.type ?? 'personal',
status: (u.status ?? 'inactive') as UserStatus, // treat null/undefined as inactive
registeredAt: u.registeredAt ?? u.createdAt ?? new Date().toISOString(),
}))
}, [users]) }, [users])
// Main widget rows (latest 5) - use normalized when provided, else dummy
const sorted = useMemo(() => {
const data = (normalizedUsers.length > 0 ? normalizedUsers : baseUsers).slice()
return data.sort((a, b) => new Date(b.registeredAt).getTime() - new Date(a.registeredAt).getTime())
}, [normalizedUsers])
const rows = sorted.slice(0, 5) const rows = sorted.slice(0, 5)
// NEW: total registered count for badge (from provided users or dummy full list) // Total badge: prefer normalized list length, else dummy all
const totalRegistered = useMemo(() => { const totalRegistered = useMemo(() => {
return users && users.length ? users.length : allDummyUsers.length return normalizedUsers.length ? normalizedUsers.length : allDummyUsers.length
}, [users]) }, [normalizedUsers])
// Modal state // Modal state
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
@ -118,11 +130,11 @@ export default function RegisteredUserList({ users, loading }: Props) {
const [page, setPage] = useState(1) const [page, setPage] = useState(1)
const pageSize = 10 const pageSize = 10
// Full dataset for modal (dummy for now) // Full dataset for modal
const allRows = useMemo(() => { const allRows = useMemo(() => {
const data = users && users.length ? users : allDummyUsers const data = normalizedUsers.length ? normalizedUsers : allDummyUsers
return data.sort((a, b) => new Date(b.registeredAt).getTime() - new Date(a.registeredAt).getTime()) return data.sort((a, b) => new Date(b.registeredAt).getTime() - new Date(a.registeredAt).getTime())
}, [users]) }, [normalizedUsers])
const filtered = useMemo(() => { const filtered = useMemo(() => {
return allRows.filter(r => { return allRows.filter(r => {
@ -130,11 +142,7 @@ export default function RegisteredUserList({ users, loading }: Props) {
if (statusFilter !== 'all' && r.status !== statusFilter) return false if (statusFilter !== 'all' && r.status !== statusFilter) return false
if (!query.trim()) return true if (!query.trim()) return true
const q = query.toLowerCase() const q = query.toLowerCase()
return ( return r.name.toLowerCase().includes(q) || r.email.toLowerCase().includes(q)
r.name.toLowerCase().includes(q) ||
r.email.toLowerCase().includes(q)
// CHANGED: remove refCode match (not provided by backend)
)
}) })
}, [allRows, query, typeFilter, statusFilter]) }, [allRows, query, typeFilter, statusFilter])
@ -297,6 +305,7 @@ export default function RegisteredUserList({ users, loading }: Props) {
> >
<option value="all">All Status</option> <option value="all">All Status</option>
<option value="active">Active</option> <option value="active">Active</option>
<option value="inactive">Inactive</option> {/* NEW */}
<option value="pending">Pending</option> <option value="pending">Pending</option>
<option value="blocked">Blocked</option> <option value="blocked">Blocked</option>
</select> </select>