feat(logs): Add various log pages for tracking user activities and system events

This commit is contained in:
web
2025-08-26 11:29:12 -07:00
parent 4f7cc807af
commit d85af491aa
28 changed files with 876 additions and 252 deletions
@@ -8,6 +8,7 @@ export interface IParams {
key: string;
placeholder?: string;
options?: { label: string; value: string }[];
type?: 'text' | 'select' | 'date';
}
interface ColumnFilterProps<TData> {
table: Table<TData>;
@@ -28,10 +29,18 @@ export function ColumnFilter<TData>({ table, params, filters }: ColumnFilterProp
});
};
const toDateInput = (d: Date) => {
const pad = (n: number) => String(n).padStart(2, '0');
const yyyy = d.getFullYear();
const MM = pad(d.getMonth() + 1);
const dd = pad(d.getDate());
return `${yyyy}-${MM}-${dd}`;
};
return (
<div className='flex gap-2'>
{params.map((param) => {
if (param.options) {
if (param.options || param.type === 'select') {
return (
<Combobox
key={param.key}
@@ -45,6 +54,28 @@ export function ColumnFilter<TData>({ table, params, filters }: ColumnFilterProp
/>
);
}
if (param.type === 'date') {
const raw = filters[param.key];
const inputValue =
typeof raw === 'number'
? toDateInput(new Date(raw))
: typeof raw === 'string'
? raw
: '';
return (
<Input
key={param.key}
className='block w-32'
type='date'
placeholder={param.placeholder}
value={inputValue}
onChange={(event) => {
const v = event.target.value;
updateFilter(param.key, v || '');
}}
/>
);
}
return (
<Input
key={param.key}
@@ -8,6 +8,7 @@ export interface IParams {
key: string;
placeholder?: string;
options?: { label: string; value: string }[];
type?: 'text' | 'select' | 'date';
}
interface ColumnFilterProps<TData> {
table: Table<TData>;
@@ -28,10 +29,18 @@ export function ColumnFilter<TData>({ table, params, filters }: ColumnFilterProp
});
};
const toDateInput = (d: Date) => {
const pad = (n: number) => String(n).padStart(2, '0');
const yyyy = d.getFullYear();
const MM = pad(d.getMonth() + 1);
const dd = pad(d.getDate());
return `${yyyy}-${MM}-${dd}`;
};
return (
<div className='flex gap-2'>
{params.map((param) => {
if (param.options) {
if (param.options || param.type === 'select') {
return (
<Combobox
key={param.key}
@@ -45,6 +54,28 @@ export function ColumnFilter<TData>({ table, params, filters }: ColumnFilterProp
/>
);
}
if (param.type === 'date') {
const raw = filters[param.key];
const inputValue =
typeof raw === 'number'
? toDateInput(new Date(raw))
: typeof raw === 'string'
? raw
: '';
return (
<Input
key={param.key}
className='block min-w-32'
type='date'
placeholder={param.placeholder}
value={inputValue}
onChange={(event) => {
const v = event.target.value;
updateFilter(param.key, v || '');
}}
/>
);
}
return (
<Input
key={param.key}