implemented
This commit is contained in:
parent
a31bd8246c
commit
d3638e2e69
18 changed files with 1643 additions and 120 deletions
|
|
@ -6,35 +6,18 @@ import { api } from "../../api";
|
|||
import { sharedStyles } from "../../styles/shared";
|
||||
import { Header } from "../../components/Header";
|
||||
import { useRequireAuth } from "../../hooks/useRequireAuth";
|
||||
import { components } from "../../generated/api";
|
||||
import constants from "../../../../shared/constants.json";
|
||||
|
||||
interface InviteRecord {
|
||||
id: number;
|
||||
identifier: string;
|
||||
godfather_id: number;
|
||||
godfather_email: string;
|
||||
status: string;
|
||||
used_by_id: number | null;
|
||||
used_by_email: string | null;
|
||||
created_at: string;
|
||||
spent_at: string | null;
|
||||
revoked_at: string | null;
|
||||
}
|
||||
const { READY, SPENT, REVOKED } = constants.inviteStatuses;
|
||||
|
||||
interface PaginatedResponse<T> {
|
||||
records: T[];
|
||||
total: number;
|
||||
page: number;
|
||||
per_page: number;
|
||||
total_pages: number;
|
||||
}
|
||||
|
||||
interface UserOption {
|
||||
id: number;
|
||||
email: string;
|
||||
}
|
||||
// Use generated types from OpenAPI schema
|
||||
type InviteRecord = components["schemas"]["InviteResponse"];
|
||||
type PaginatedInvites = components["schemas"]["PaginatedResponse_InviteResponse_"];
|
||||
type UserOption = components["schemas"]["AdminUserResponse"];
|
||||
|
||||
export default function AdminInvitesPage() {
|
||||
const [data, setData] = useState<PaginatedResponse<InviteRecord> | null>(null);
|
||||
const [data, setData] = useState<PaginatedInvites | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [page, setPage] = useState(1);
|
||||
const [statusFilter, setStatusFilter] = useState<string>("");
|
||||
|
|
@ -63,7 +46,7 @@ export default function AdminInvitesPage() {
|
|||
if (status) {
|
||||
url += `&status=${status}`;
|
||||
}
|
||||
const data = await api.get<PaginatedResponse<InviteRecord>>(url);
|
||||
const data = await api.get<PaginatedInvites>(url);
|
||||
setData(data);
|
||||
} catch (err) {
|
||||
setData(null);
|
||||
|
|
@ -117,11 +100,11 @@ export default function AdminInvitesPage() {
|
|||
|
||||
const getStatusBadgeStyle = (status: string) => {
|
||||
switch (status) {
|
||||
case "ready":
|
||||
case READY:
|
||||
return styles.statusReady;
|
||||
case "spent":
|
||||
case SPENT:
|
||||
return styles.statusSpent;
|
||||
case "revoked":
|
||||
case REVOKED:
|
||||
return styles.statusRevoked;
|
||||
default:
|
||||
return {};
|
||||
|
|
@ -198,9 +181,9 @@ export default function AdminInvitesPage() {
|
|||
style={styles.filterSelect}
|
||||
>
|
||||
<option value="">All statuses</option>
|
||||
<option value="ready">Ready</option>
|
||||
<option value="spent">Spent</option>
|
||||
<option value="revoked">Revoked</option>
|
||||
<option value={READY}>Ready</option>
|
||||
<option value={SPENT}>Spent</option>
|
||||
<option value={REVOKED}>Revoked</option>
|
||||
</select>
|
||||
<span style={styles.totalCount}>
|
||||
{data?.total ?? 0} invites
|
||||
|
|
@ -240,7 +223,7 @@ export default function AdminInvitesPage() {
|
|||
</td>
|
||||
<td style={styles.tdDate}>{formatDate(record.created_at)}</td>
|
||||
<td style={styles.td}>
|
||||
{record.status === "ready" && (
|
||||
{record.status === READY && (
|
||||
<button
|
||||
onClick={() => handleRevoke(record.id)}
|
||||
style={styles.revokeButton}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue