store user login

This commit is contained in:
2026-08-25 18:00:16 +05:30
parent 1dc582ba07
commit 517a99d577
62 changed files with 8059 additions and 650 deletions

View File

@@ -321,6 +321,7 @@ export function TillDrawer({
locationid,
roles,
shifts,
cashierOnly = false,
onClose,
}: {
row: PosUser | null;
@@ -328,13 +329,22 @@ export function TillDrawer({
locationid: number;
roles: PosRole[];
shifts: StaffShift[];
/**
* True in the Store user workspace.
*
* A shop provisions cashiers, not supervisors. The backend agrees from the
* other side — only roleid 7 may manage till users — so a supervisor is
* issued by the merchant and creates their own cashiers at the terminal. The
* picker is absent rather than disabled: there is nothing to choose.
*/
cashierOnly?: boolean;
onClose: () => void;
}) {
const queryClient = useQueryClient();
const isNew = row === null;
const [fullName, setFullName] = useState(row?.full_name ?? '');
const [role, setRole] = useState(row?.role?.toLowerCase() ?? 'cashier');
const [role, setRole] = useState(cashierOnly ? 'cashier' : (row?.role?.toLowerCase() ?? 'cashier'));
const [contactno, setContactno] = useState(row?.contactno ?? '');
const [pin, setPin] = useState('');
const [shiftId, setShiftId] = useState(String(row?.shift_id ?? 0));
@@ -454,7 +464,13 @@ export function TillDrawer({
return (
<Sheet
title={isNew ? 'Add a till account' : (row.full_name ?? 'Edit till account')}
title={
isNew
? cashierOnly
? 'Add a cashier'
: 'Add a till account'
: (row.full_name ?? 'Edit till account')
}
subtitle={
isNew ? 'Signs in at a till — no console login' : `Till user ${row.user_id}`
}
@@ -477,12 +493,29 @@ export function TillDrawer({
<TextInput label={<span>Full name <span style={{ color: 'var(--color-error)' }}>*</span></span> as any} value={fullName} onChange={setFullName} />
<Selector label="Role" value={role} onChange={setRole} options={roleOptions} />
{chosenRole?.description ? (
<Text type="body" size="xsm" color="secondary">
{chosenRole.description}
</Text>
) : null}
{/* The role is shown either way — a form that silently decides a
field leaves the reader wondering what was decided. A shop just
cannot change it: the merchant issues supervisors, and the backend
only lets roleid 7 manage till users at all. */}
{cashierOnly ? (
<Selector
label="Role"
value="cashier"
onChange={() => undefined}
options={[{ value: 'cashier', label: 'Cashier' }]}
isDisabled
description="Supervisors are issued by your store administrator."
/>
) : (
<>
<Selector label="Role" value={role} onChange={setRole} options={roleOptions} />
{chosenRole?.description ? (
<Text type="body" size="xsm" color="secondary">
{chosenRole.description}
</Text>
) : null}
</>
)}
<TextInput
label={<span>Mobile <span style={{ color: 'var(--color-error)' }}>*</span></span> as any}