feat: admin panel and invite acceptance UI
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { Profile, Client, ClientCreate, Event, EventCreate, Email, EmailGenerate, User } from '@/types';
|
||||
import type { Profile, Client, ClientCreate, Event, EventCreate, Email, EmailGenerate, User, Invite } from '@/types';
|
||||
|
||||
const API_BASE = import.meta.env.PROD
|
||||
? 'https://api.thenetwork.donovankelly.xyz/api'
|
||||
@@ -223,6 +223,60 @@ class ApiClient {
|
||||
async deleteEmail(id: string): Promise<void> {
|
||||
await this.fetch(`/emails/${id}`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
// Admin
|
||||
async getUsers(): Promise<User[]> {
|
||||
return this.fetch('/admin/users');
|
||||
}
|
||||
|
||||
async updateUserRole(userId: string, role: string): Promise<void> {
|
||||
await this.fetch(`/admin/users/${userId}/role`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ role }),
|
||||
});
|
||||
}
|
||||
|
||||
async deleteUser(userId: string): Promise<void> {
|
||||
await this.fetch(`/admin/users/${userId}`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
async createInvite(data: { email: string; name: string; role?: string }): Promise<Invite & { setupUrl: string }> {
|
||||
return this.fetch('/admin/invites', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
}
|
||||
|
||||
async getInvites(): Promise<Invite[]> {
|
||||
return this.fetch('/admin/invites');
|
||||
}
|
||||
|
||||
async deleteInvite(id: string): Promise<void> {
|
||||
await this.fetch(`/admin/invites/${id}`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
// Invite acceptance (public - no auth)
|
||||
async validateInvite(token: string): Promise<{ id: string; email: string; name: string; role: string; expiresAt: string }> {
|
||||
const response = await fetch(`${AUTH_BASE}/auth/invite/${token}`);
|
||||
if (!response.ok) {
|
||||
const error = await response.json().catch(() => ({ error: 'Invalid invite' }));
|
||||
throw new Error(error.error || 'Invalid invite');
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async acceptInvite(token: string, password: string, name?: string): Promise<{ success: boolean; token?: string }> {
|
||||
const response = await fetch(`${AUTH_BASE}/auth/invite/${token}/accept`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ password, name }),
|
||||
});
|
||||
if (!response.ok) {
|
||||
const error = await response.json().catch(() => ({ error: 'Failed to accept invite' }));
|
||||
throw new Error(error.error || 'Failed to accept invite');
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
}
|
||||
|
||||
export const api = new ApiClient();
|
||||
|
||||
Reference in New Issue
Block a user