Skip to content

Commit 7ac5501

Browse files
committed
Initial COmmit
1 parent 1d4d765 commit 7ac5501

12 files changed

Lines changed: 386 additions & 61 deletions

File tree

.env.webui

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# =============================================================================
2+
# WEBUI
3+
# =============================================================================
4+
VITE_API_URL=https://capyrpi.org

src/api/auth.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { apiRequest } from './client';
2+
import type { AuthUser } from '../types/User.ts';
3+
4+
export const authApi = {
5+
// Get current user
6+
getMe: () => apiRequest<AuthUser>('/auth/me'),
7+
8+
// Initiate Google OAth
9+
loginWithGoogle: () => {
10+
window.location.href = '/auth/google';
11+
},
12+
13+
// Initiate Microsoft OAuth
14+
loginWithMicrosoft: () => {
15+
window.location.href = '/auth/microsoft';
16+
},
17+
18+
// Logout
19+
logout: () =>
20+
apiRequest<void>('/auth/logout', {
21+
method: 'POST',
22+
}),
23+
24+
// Refresh token
25+
refresh: () =>
26+
apiRequest<void>('/auth/refresh', {
27+
method: 'POST',
28+
}),
29+
};

src/api/client.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
2+
3+
// All fields are optional since there are defaults
4+
interface RequestOptions<TBody> {
5+
method?: HttpMethod;
6+
body?: TBody;
7+
headers?: HeadersInit;
8+
credentials?: RequestCredentials;
9+
}
10+
11+
// TResponse: expected response from the server
12+
// TBody: expected shape of the body (default: unknown)
13+
// Params: endpoint and RequestOptions
14+
export async function apiRequest<TResponse, TBody = unknown>(
15+
endpoint: string,
16+
options: RequestOptions<TBody> = {}
17+
): Promise<TResponse> {
18+
const { method = 'GET', body, headers = {}, credentials = 'include' } = options; // defaults
19+
20+
const response = await fetch(endpoint, {
21+
method,
22+
headers: {
23+
'Content-Type': 'application/json',
24+
...headers,
25+
},
26+
credentials,
27+
body: body ? JSON.stringify(body) : undefined,
28+
});
29+
30+
// Error handling
31+
if (!response.ok) {
32+
const errorText = await response.text();
33+
throw new Error(`API Error: ${response.status} - ${errorText}`);
34+
}
35+
36+
// Success
37+
return response.json();
38+
}

src/api/events.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { apiRequest } from './client';
2+
import type { CreateEvent, UpdateEvent, RegisterEvent, Event, EventUser } from '../types/Event.ts';
3+
import type { QueryParams } from '../types/QueryParams.ts';
4+
5+
export const eventsApi = {
6+
// Get all events
7+
getAll: (params?: QueryParams) => {
8+
const query = new URLSearchParams();
9+
if (params?.limit !== undefined) {
10+
query.append('limit', params.limit.toString());
11+
}
12+
if (params?.offset !== undefined) {
13+
query.append('offset', params.offset.toString());
14+
}
15+
const queryString = query.toString();
16+
return apiRequest<Event[]>(queryString ? `/events?${queryString}` : '/events');
17+
},
18+
19+
// Create an event
20+
create: (data: CreateEvent) =>
21+
apiRequest<Event>(`/events`, {
22+
method: 'POST',
23+
body: data,
24+
}),
25+
26+
// List events by organization
27+
getFromOrganization: (oid: string, params?: QueryParams) => {
28+
const query = new URLSearchParams();
29+
if (params?.limit !== undefined) {
30+
query.append('limit', params.limit.toString());
31+
}
32+
if (params?.offset !== undefined) {
33+
query.append('offset', params.offset.toString());
34+
}
35+
const queryString = query.toString();
36+
return apiRequest<Event[]>(queryString ? `/events/org/${oid}?${queryString}` : `/events/org/${oid}`);
37+
},
38+
39+
// Get event
40+
getById: (eid: string) => apiRequest<Event>(`/events/${eid}`),
41+
42+
// Update event
43+
update: (eid: string, data: UpdateEvent) =>
44+
apiRequest<Event, UpdateEvent>(`/events/${eid}`, {
45+
method: 'PUT',
46+
body: data,
47+
}),
48+
49+
// Delete event
50+
delete: (eid: string) =>
51+
apiRequest<void>(`/events/${eid}`, {
52+
method: 'DELETE',
53+
}),
54+
55+
// Register for event
56+
register: (eid: string, data: RegisterEvent) =>
57+
apiRequest<void, RegisterEvent>(`/events/${eid}/register`, {
58+
method: 'POST',
59+
body: data,
60+
}),
61+
62+
// Unregister from event
63+
unregister: (eid: string, data: RegisterEvent) =>
64+
apiRequest<void, RegisterEvent>(`/events/${eid}/register`, {
65+
method: 'DELETE',
66+
body: data,
67+
}),
68+
69+
// Get users registered for an event
70+
getUsers: (eid: string) => apiRequest<EventUser>(`/events/${eid}/registrations`),
71+
};

src/api/organizations.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { apiRequest } from './client';
2+
import type {
3+
Organization,
4+
CreateOrganization,
5+
UpdateOrganization,
6+
OrganizationUser,
7+
ManageOrganizationUser,
8+
} from '../types/Organization.ts';
9+
import type { Event } from '../types/Event.ts';
10+
import type { QueryParams } from '../types/QueryParams.ts';
11+
12+
export const organizationsApi = {
13+
// Get all organizations
14+
getAll: (params?: QueryParams) => {
15+
const query = new URLSearchParams();
16+
if (params?.limit !== undefined) {
17+
query.append('limit', params.limit.toString());
18+
}
19+
if (params?.offset !== undefined) {
20+
query.append('offset', params.offset.toString());
21+
}
22+
const queryString = query.toString();
23+
return apiRequest<Organization[]>(queryString ? `/organizations?${queryString}` : '/organizations');
24+
},
25+
26+
// Create organization
27+
create: (data: CreateOrganization) =>
28+
apiRequest<Organization, CreateOrganization>(`/events`, {
29+
method: 'POST',
30+
body: data,
31+
}),
32+
33+
// Get organization
34+
getById: (oid: string) => apiRequest<Organization>(`/organizations/${oid}`),
35+
36+
// Update organization
37+
update: (oid: string, data: UpdateOrganization) =>
38+
apiRequest<Organization, UpdateOrganization>(`/organizations/${oid}`, {
39+
method: 'PUT',
40+
body: data,
41+
}),
42+
43+
// Delete organization
44+
delete: (oid: string) =>
45+
apiRequest<void>(`/organizations/${oid}`, {
46+
method: 'DELETE',
47+
}),
48+
49+
// Get organization's events
50+
events: (oid: string, params?: QueryParams) => {
51+
const query = new URLSearchParams();
52+
if (params?.limit !== undefined) {
53+
query.append('limit', params.limit.toString());
54+
}
55+
if (params?.offset !== undefined) {
56+
query.append('offset', params.offset.toString());
57+
}
58+
const queryString = query.toString();
59+
return apiRequest<Event[]>(
60+
queryString ? `/organizations/${oid}/events?${queryString}` : `/organizations/${oid}/events`
61+
);
62+
},
63+
// Get organization's members
64+
getMembers: (oid: string) => apiRequest<OrganizationUser>(`/organizations/${oid}/members`),
65+
66+
// Add member to organization
67+
addMember: (oid: string, data: ManageOrganizationUser) =>
68+
apiRequest<void, ManageOrganizationUser>(`/organizations/${oid}/members`, {
69+
method: 'POST',
70+
body: data,
71+
}),
72+
73+
// Remove organization member
74+
deleteMember: (oid: string, data: ManageOrganizationUser) =>
75+
apiRequest<void, ManageOrganizationUser>(`/organizations/${oid}/members`, {
76+
method: 'DELETE',
77+
body: data,
78+
}),
79+
};

src/api/users.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { apiRequest } from './client';
2+
import type { User } from '../types/User.ts';
3+
import type { Event } from '../types/Event.ts';
4+
import type { Organization } from '../types/Organization.ts';
5+
6+
export const usersApi = {
7+
// Get user by ID
8+
getById: (id: string) => apiRequest<User>(`/users/${id}`),
9+
10+
// Update user
11+
update: (id: string, data: User) =>
12+
apiRequest<User>(`/users/${id}`, {
13+
method: 'POST',
14+
body: data,
15+
}),
16+
17+
// Delete user
18+
delete: (id: string) =>
19+
apiRequest<void>(`/users/${id}`, {
20+
method: 'DELETE',
21+
}),
22+
23+
// Get user's events
24+
getEvents: (id: string) => apiRequest<Event[]>(`/users/${id}/events`),
25+
26+
// Get user's organizations
27+
getOrganizations: (id: string) => apiRequest<Organization[]>(`/users/${id}/organizations`),
28+
};

0 commit comments

Comments
 (0)