This commit is contained in:
2026-02-10 12:00:32 -05:00
parent bddd0dbe87
commit 26024c1426
10 changed files with 62 additions and 10 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
app/.DS_Store vendored

Binary file not shown.

View File

@@ -1,16 +1,16 @@
{
"files": {
"main.css": "/static/css/main.6d8e0960.css",
"main.js": "/static/js/main.dd937a88.js",
"main.js": "/static/js/main.e64707d9.js",
"static/js/787.c4e7f8f9.chunk.js": "/static/js/787.c4e7f8f9.chunk.js",
"static/media/landing.png": "/static/media/landing.d4c6072db7a67dff6a78.png",
"index.html": "/index.html",
"main.6d8e0960.css.map": "/static/css/main.6d8e0960.css.map",
"main.dd937a88.js.map": "/static/js/main.dd937a88.js.map",
"main.e64707d9.js.map": "/static/js/main.e64707d9.js.map",
"787.c4e7f8f9.chunk.js.map": "/static/js/787.c4e7f8f9.chunk.js.map"
},
"entrypoints": [
"static/css/main.6d8e0960.css",
"static/js/main.dd937a88.js"
"static/js/main.e64707d9.js"
]
}

View File

@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"><link rel="manifest" href="/manifest.json"/><title>Worldshine Transportation</title><script defer="defer" src="/static/js/main.dd937a88.js"></script><link href="/static/css/main.6d8e0960.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"><link rel="manifest" href="/manifest.json"/><title>Worldshine Transportation</title><script defer="defer" src="/static/js/main.e64707d9.js"></script><link href="/static/css/main.6d8e0960.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
client/.DS_Store vendored

Binary file not shown.

View File

@@ -31,6 +31,7 @@ const DashboardCustomersList = ({ additionalButtons, showBreadcrumb = false, tit
const [avatarData, setAvatarData] = useState(null);
const [avatarCustomerName, setAvatarCustomerName] = useState('');
const [avatarLoading, setAvatarLoading] = useState(false);
const [customerAvatars, setCustomerAvatars] = useState({});
const [columns, setColumns] = useState([
{
key: 'name',
@@ -143,6 +144,28 @@ const DashboardCustomersList = ({ additionalButtons, showBreadcrumb = false, tit
})
}, []);
// Load avatars for customers - same approach as ViewCustomer
useEffect(() => {
if (customers.length === 0) return;
customers.forEach((customer) => {
if (customerAvatars[customer.id] !== undefined) return; // Already loaded or attempted
// Mark as loading to prevent duplicate requests
setCustomerAvatars(prev => ({ ...prev, [customer.id]: false }));
CustomerService.getAvatar(customer.id)
.then(result => {
if (result?.data) {
// Store raw data exactly like ViewCustomer does
setCustomerAvatars(prev => ({ ...prev, [customer.id]: result.data }));
} else {
setCustomerAvatars(prev => ({ ...prev, [customer.id]: null }));
}
})
.catch(() => {
setCustomerAvatars(prev => ({ ...prev, [customer.id]: null }));
});
});
}, [customers]);
useEffect(() => {
let filtered = customers;
@@ -313,7 +336,36 @@ const DashboardCustomersList = ({ additionalButtons, showBreadcrumb = false, tit
filteredCustomers.map((customer, index) => <tr key={customer.id}>
<td className="td-checkbox"><input type="checkbox" checked={selectedItems.includes(customer.id)} onClick={()=>toggleItem(customer?.id)}/></td>
<td className="td-index">{index + 1}</td>
{columns.find(col => col.key === 'name')?.show && <td> {AuthService.canAddOrEditCustomers() && <PencilSquare size={16} className="clickable me-2" onClick={() => goToView(customer?.id)}></PencilSquare>} {AuthService.canViewCustomers() && <PersonSquare onClick={() => showProfilePicture(customer)} size={16} className="clickable me-2" />} {customer?.name}</td>}
{columns.find(col => col.key === 'name')?.show && <td style={{ verticalAlign: 'middle' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
{AuthService.canViewCustomers() && (
customerAvatars[customer.id] && customerAvatars[customer.id] !== false ? (
<img
src={`data:image/png;base64, ${customerAvatars[customer.id]}`}
alt={customer?.name}
onClick={() => showProfilePicture(customer)}
style={{
width: '64px',
height: '64px',
borderRadius: '8px',
objectFit: 'cover',
cursor: 'pointer',
flexShrink: 0
}}
/>
) : (
<PersonSquare
onClick={() => showProfilePicture(customer)}
size={64}
className="clickable"
style={{ flexShrink: 0, color: '#ccc' }}
/>
)
)}
{AuthService.canAddOrEditCustomers() && <PencilSquare size={16} className="clickable" onClick={() => goToView(customer?.id)} style={{ flexShrink: 0 }}></PencilSquare>}
<span>{customer?.name}</span>
</div>
</td>}
{columns.find(col => col.key === 'chinese_name')?.show && <td>{customer?.name_cn}</td>}
{columns.find(col => col.key === 'email')?.show && <td>{customer?.email}</td>}
{columns.find(col => col.key === 'type')?.show && <td>{customer?.type}</td>}

View File

@@ -5,7 +5,7 @@ function Home() {
const navigate = useNavigate();
useEffect(() => {
if (localStorage.getItem('user') && localStorage.getItem('token')) {
navigate('/admin')
navigate('/dashboard/dashboard')
}
})