update ui update and fix layout issue
This commit is contained in:
300
src/features/settings/components/TeamManagement.tsx
Normal file
300
src/features/settings/components/TeamManagement.tsx
Normal file
@@ -0,0 +1,300 @@
|
||||
'use client';
|
||||
|
||||
import {useState} from 'react';
|
||||
import {proportional, pixel} from '@astryxdesign/core/Table';
|
||||
import {ResponsiveTable} from '@/shared/components/patterns/ResponsiveTable';
|
||||
import type {TableColumn} from '@astryxdesign/core/Table';
|
||||
import {VStack, HStack} from '@astryxdesign/core/Layout';
|
||||
import {Text, Heading} from '@astryxdesign/core/Text';
|
||||
import {Badge} from '@astryxdesign/core/Badge';
|
||||
import {Button} from '@astryxdesign/core/Button';
|
||||
import {Icon} from '@astryxdesign/core/Icon';
|
||||
import {Avatar} from '@astryxdesign/core/Avatar';
|
||||
import {DropdownMenu} from '@astryxdesign/core/DropdownMenu';
|
||||
import {TextInput} from '@astryxdesign/core/TextInput';
|
||||
import {Selector} from '@astryxdesign/core/Selector';
|
||||
import {useToast} from '@astryxdesign/core/Toast';
|
||||
import {StaticPanel} from '@/shared/components/patterns/PanelCard';
|
||||
|
||||
export interface StaffUser extends Record<string, unknown> {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
role: 'Owner' | 'Manager' | 'Cashier' | 'Marketing' | 'Support';
|
||||
storeName: string;
|
||||
status: 'active' | 'suspended' | 'invited';
|
||||
lastLogin: string;
|
||||
}
|
||||
|
||||
const INITIAL_STAFF: StaffUser[] = [
|
||||
{
|
||||
id: 'usr-1',
|
||||
name: 'Aravind',
|
||||
email: 'aravind@nearle.in',
|
||||
role: 'Owner',
|
||||
storeName: 'All stores',
|
||||
status: 'active',
|
||||
lastLogin: 'Just now',
|
||||
},
|
||||
{
|
||||
id: 'usr-2',
|
||||
name: 'Vikram Seth',
|
||||
email: 'vikram@nearle.in',
|
||||
role: 'Manager',
|
||||
storeName: 'Indiranagar Flagship',
|
||||
status: 'active',
|
||||
lastLogin: 'Today, 14:20',
|
||||
},
|
||||
{
|
||||
id: 'usr-3',
|
||||
name: 'Priya Sharma',
|
||||
email: 'priya@nearle.in',
|
||||
role: 'Cashier',
|
||||
storeName: 'Koramangala 80ft',
|
||||
status: 'active',
|
||||
lastLogin: 'Today, 09:15',
|
||||
},
|
||||
{
|
||||
id: 'usr-4',
|
||||
name: 'Rahul Verma',
|
||||
email: 'rahul@nearle.in',
|
||||
role: 'Marketing',
|
||||
storeName: 'All stores',
|
||||
status: 'invited',
|
||||
lastLogin: 'Pending accept',
|
||||
},
|
||||
{
|
||||
id: 'usr-5',
|
||||
name: 'Deepa Nair',
|
||||
email: 'deepa@nearle.in',
|
||||
role: 'Cashier',
|
||||
storeName: 'Whitefield Main',
|
||||
status: 'suspended',
|
||||
lastLogin: '3 days ago',
|
||||
},
|
||||
];
|
||||
|
||||
export function TeamManagement() {
|
||||
const toast = useToast();
|
||||
const [staffList, setStaffList] = useState<StaffUser[]>(INITIAL_STAFF);
|
||||
const [isAdding, setIsAdding] = useState(false);
|
||||
const [name, setName] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [role, setRole] = useState<'Owner' | 'Manager' | 'Cashier' | 'Marketing' | 'Support'>('Manager');
|
||||
const [storeName, setStoreName] = useState('Indiranagar Flagship');
|
||||
|
||||
const handleAddStaff = () => {
|
||||
if (!name.trim() || !email.trim()) {
|
||||
toast({type: 'error', body: 'Name and Email are required'});
|
||||
return;
|
||||
}
|
||||
const newUser: StaffUser = {
|
||||
id: `usr-${Date.now()}`,
|
||||
name,
|
||||
email,
|
||||
role,
|
||||
storeName,
|
||||
status: 'invited',
|
||||
lastLogin: 'Pending accept',
|
||||
};
|
||||
setStaffList((prev) => [newUser, ...prev]);
|
||||
setName('');
|
||||
setEmail('');
|
||||
setIsAdding(false);
|
||||
toast({body: `Invitation sent to ${email}`});
|
||||
};
|
||||
|
||||
const handleToggleStatus = (id: string) => {
|
||||
setStaffList((prev) =>
|
||||
prev.map((s) => {
|
||||
if (s.id !== id) return s;
|
||||
const nextStatus = s.status === 'suspended' ? 'active' : 'suspended';
|
||||
toast({body: `${s.name} status updated to ${nextStatus}`});
|
||||
return {...s, status: nextStatus};
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleResetPassword = (emailStr: string) => {
|
||||
toast({body: `Password reset link sent to ${emailStr}`});
|
||||
};
|
||||
|
||||
const handleRemove = (id: string, nameStr: string) => {
|
||||
setStaffList((prev) => prev.filter((s) => s.id !== id));
|
||||
toast({body: `${nameStr} removed from team`});
|
||||
};
|
||||
|
||||
const columns: TableColumn<StaffUser>[] = [
|
||||
{
|
||||
key: 'name',
|
||||
header: 'Staff Member',
|
||||
width: proportional(2),
|
||||
renderCell: (row) => (
|
||||
<HStack gap={3} vAlign="center">
|
||||
<Avatar name={row.name} size="sm" tooltip={false} />
|
||||
<VStack gap={0}>
|
||||
<Text size="sm" weight="medium">
|
||||
{row.name}
|
||||
</Text>
|
||||
<Text size="sm" color="secondary">
|
||||
{row.email}
|
||||
</Text>
|
||||
</VStack>
|
||||
</HStack>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'role',
|
||||
header: 'Role',
|
||||
width: proportional(1),
|
||||
renderCell: (row) => (
|
||||
<Badge
|
||||
variant={row.role === 'Owner' ? 'info' : 'neutral'}
|
||||
label={row.role}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'storeName',
|
||||
header: 'Assigned Store',
|
||||
width: proportional(1.5),
|
||||
renderCell: (row) => <Text size="sm">{row.storeName}</Text>,
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
header: 'Status',
|
||||
width: pixel(110),
|
||||
renderCell: (row) => {
|
||||
const v =
|
||||
row.status === 'active'
|
||||
? 'success'
|
||||
: row.status === 'suspended'
|
||||
? 'error'
|
||||
: 'warning';
|
||||
return <Badge variant={v} label={row.status} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'lastLogin',
|
||||
header: 'Last Login',
|
||||
width: proportional(1.2),
|
||||
renderCell: (row) => (
|
||||
<Text size="sm" color="secondary">
|
||||
{row.lastLogin}
|
||||
</Text>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
header: 'Actions',
|
||||
align: 'center',
|
||||
width: pixel(160),
|
||||
renderCell: (row) =>
|
||||
row.role === 'Owner' ? (
|
||||
<HStack hAlign="center">
|
||||
<Text size="sm" color="secondary">
|
||||
Primary Owner
|
||||
</Text>
|
||||
</HStack>
|
||||
) : (
|
||||
<HStack hAlign="center">
|
||||
<DropdownMenu
|
||||
button={{
|
||||
variant: 'secondary',
|
||||
size: 'sm',
|
||||
label: 'Manage',
|
||||
icon: <Icon icon="moreHorizontal" size="sm" />,
|
||||
}}
|
||||
menuWidth={180}
|
||||
items={[
|
||||
{
|
||||
label: row.status === 'suspended' ? 'Reactivate staff' : 'Suspend staff',
|
||||
onClick: () => handleToggleStatus(row.id),
|
||||
},
|
||||
{
|
||||
label: 'Reset password',
|
||||
onClick: () => handleResetPassword(row.email),
|
||||
},
|
||||
{type: 'divider'},
|
||||
{
|
||||
label: 'Remove from team',
|
||||
onClick: () => handleRemove(row.id, row.name),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</HStack>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<VStack gap={5}>
|
||||
<StaticPanel
|
||||
title="Team Directory & Staff Access"
|
||||
subtitle="Manage store assignments, role permissions, password resets and account statuses."
|
||||
actions={
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
label={isAdding ? 'Cancel' : 'Add Staff Member'}
|
||||
onClick={() => setIsAdding(!isAdding)}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<VStack gap={4}>
|
||||
{isAdding ? (
|
||||
<VStack gap={3} padding={4}>
|
||||
<Heading level={3}>Invite New Staff Member</Heading>
|
||||
<HStack gap={3} vAlign="end" wrap="wrap">
|
||||
<TextInput
|
||||
label="Full Name"
|
||||
value={name}
|
||||
onChange={setName}
|
||||
placeholder="e.g. Ananya Rao"
|
||||
/>
|
||||
<TextInput
|
||||
label="Work Email"
|
||||
value={email}
|
||||
onChange={setEmail}
|
||||
placeholder="ananya@nearle.in"
|
||||
/>
|
||||
<Selector
|
||||
label="Role"
|
||||
value={role}
|
||||
onChange={(v) =>
|
||||
setRole(v as 'Owner' | 'Manager' | 'Cashier' | 'Marketing' | 'Support')
|
||||
}
|
||||
options={['Manager', 'Cashier', 'Marketing', 'Support']}
|
||||
/>
|
||||
<Selector
|
||||
label="Assigned Store"
|
||||
value={storeName}
|
||||
onChange={(v) => setStoreName(v)}
|
||||
options={[
|
||||
'All stores',
|
||||
'Indiranagar Flagship',
|
||||
'Koramangala 80ft',
|
||||
'Whitefield Main',
|
||||
'Jayanagar 4th Block',
|
||||
]}
|
||||
/>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
label="Send Invite"
|
||||
onClick={handleAddStaff}
|
||||
/>
|
||||
</HStack>
|
||||
</VStack>
|
||||
) : null}
|
||||
|
||||
<ResponsiveTable
|
||||
columns={columns}
|
||||
data={staffList}
|
||||
primaryKey="name"
|
||||
/>
|
||||
</VStack>
|
||||
</StaticPanel>
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user