Add frontend support for user

This commit is contained in:
Sami Abuzakuk
2025-11-01 16:05:52 +01:00
parent 374558d30f
commit e9d94f706c
14 changed files with 521 additions and 285 deletions

View File

@@ -2,6 +2,56 @@ import { env } from '$env/dynamic/public';
export const API_URL = env.PUBLIC_API_URL || 'http://localhost:8000';
// Helper to get token from localStorage
export function getToken(): string | null {
return localStorage.getItem('token');
}
// Helper to add Authorization header if token exists
export function authHeaders(headers: Record<string, string> = {}): Record<string, string> {
const token = getToken();
return token ? { ...headers, Authorization: `Bearer ${token}` } : headers;
}
/**
* Login and Register API
*/
export interface AuthResponse {
access_token: string;
token_type: string;
}
export async function login(username: string, password: string): Promise<AuthResponse> {
const form = new FormData();
form.append('username', username);
form.append('password', password);
const response = await fetch(`${API_URL}/login`, {
method: 'POST',
body: form
});
if (!response.ok) {
const data = await response.json();
throw new Error(data.detail || 'Login failed');
}
return response.json();
}
export async function register(username: string, password: string): Promise<AuthResponse> {
const response = await fetch(`${API_URL}/register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ username, password })
});
if (!response.ok) {
const data = await response.json();
throw new Error(data.detail || 'Registration failed');
}
return response.json();
}
/**
* Type definitions for Subscriptions and Notifications
*/
@@ -67,7 +117,9 @@ export interface Script {
// Fetch all scripts
export async function fetchScripts(): Promise<Script[]> {
const response = await fetch(`${API_URL}/script`);
const response = await fetch(`${API_URL}/script`, {
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to fetch scripts ' + response.statusText);
}
@@ -80,9 +132,7 @@ export async function addScript(
): Promise<Script> {
const response = await fetch(`${API_URL}/script`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify(script)
});
if (!response.ok) {
@@ -92,8 +142,10 @@ export async function addScript(
}
// Fetch all settings
export async function fetchSettings(): Promise<Settings[]> {
const response = await fetch(`${API_URL}/settings`);
export async function fetchUserSettings(): Promise<Settings> {
const response = await fetch(`${API_URL}/settings`, {
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to fetch settings ' + response.statusText);
}
@@ -102,7 +154,9 @@ export async function fetchSettings(): Promise<Settings[]> {
// Fetch a single setting by ID
export async function fetchSettingById(id: number): Promise<Settings> {
const response = await fetch(`${API_URL}/settings/${id}`);
const response = await fetch(`${API_URL}/settings/${id}`, {
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to fetch setting');
}
@@ -116,9 +170,7 @@ export async function updateSetting(
): Promise<Settings> {
const response = await fetch(`${API_URL}/settings/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ ...updatedSetting, ntfy_url: updatedSetting.ntfy_url })
});
if (!response.ok) {
@@ -129,7 +181,9 @@ export async function updateSetting(
// Fetch all subscriptions
export async function fetchSubscriptions(): Promise<Subscription[]> {
const response = await fetch(`${API_URL}/subscriptions`);
const response = await fetch(`${API_URL}/subscriptions`, {
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to fetch subscriptions');
}
@@ -138,7 +192,9 @@ export async function fetchSubscriptions(): Promise<Subscription[]> {
// Fetch subscriptions by topic
export async function getSubscription(topic_id: string): Promise<Subscription> {
const response = await fetch(`${API_URL}/subscriptions/${topic_id}`);
const response = await fetch(`${API_URL}/subscriptions/${topic_id}`, {
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to fetch subscriptions');
}
@@ -154,9 +210,7 @@ export async function addNotification(
): Promise<Notification> {
const response = await fetch(`${API_URL}/notifications`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ subscription_id: subscriptionId, title, message, priority })
});
if (!response.ok) {
@@ -169,9 +223,7 @@ export async function addNotification(
export async function setViewed(notificationId: number): Promise<Notification> {
const response = await fetch(`${API_URL}/notifications/${notificationId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ viewed: true })
});
if (!response.ok) {
@@ -184,9 +236,7 @@ export async function setViewed(notificationId: number): Promise<Notification> {
export async function addSubscription(topic: string): Promise<Subscription> {
const response = await fetch(`${API_URL}/subscriptions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ topic })
});
if (!response.ok) {
@@ -198,7 +248,8 @@ export async function addSubscription(topic: string): Promise<Subscription> {
// Delete a subscription
export async function deleteSubscription(subscriptionId: number): Promise<void> {
const response = await fetch(`${API_URL}/subscriptions/${subscriptionId}`, {
method: 'DELETE'
method: 'DELETE',
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to delete subscription');
@@ -212,7 +263,10 @@ export async function fetchSubscriptionNotifications(
offset: number = 0
): Promise<Notification[]> {
const response = await fetch(
`${API_URL}/subscriptions/${subscriptionId}/notifications?limit=${limit}&offset=${offset}`
`${API_URL}/subscriptions/${subscriptionId}/notifications?limit=${limit}&offset=${offset}`,
{
headers: authHeaders()
}
);
if (!response.ok) {
throw new Error('Failed to fetch subscription notifications');
@@ -223,7 +277,9 @@ export async function fetchSubscriptionNotifications(
// Fetch all notifications or filter by topic
export async function fetchAllNotifications(): Promise<Notification[]> {
const url = `${API_URL}/notifications`;
const response = await fetch(url);
const response = await fetch(url, {
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to fetch notifications');
}
@@ -233,7 +289,8 @@ export async function fetchAllNotifications(): Promise<Notification[]> {
// Delete a notification
export async function deleteNotification(notificationId: number): Promise<void> {
const response = await fetch(`${API_URL}/notifications/${notificationId}`, {
method: 'DELETE'
method: 'DELETE',
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to delete notification');
@@ -242,7 +299,9 @@ export async function deleteNotification(notificationId: number): Promise<void>
// Fetch a single script by ID
export async function fetchScriptById(id: number): Promise<Script> {
const response = await fetch(`${API_URL}/script/${id}`);
const response = await fetch(`${API_URL}/script/${id}`, {
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to fetch script');
}
@@ -253,9 +312,7 @@ export async function fetchScriptById(id: number): Promise<Script> {
export async function updateScript(id: number, updatedScript: Partial<Script>): Promise<Script> {
const response = await fetch(`${API_URL}/script/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify(updatedScript)
});
if (!response.ok) {
@@ -266,7 +323,9 @@ export async function updateScript(id: number, updatedScript: Partial<Script>):
// Fetch logs for a specific script
export async function fetchLogs(scriptId: number): Promise<Log[]> {
const response = await fetch(`${API_URL}/script/${scriptId}/log`);
const response = await fetch(`${API_URL}/script/${scriptId}/log`, {
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to fetch logs');
}
@@ -277,9 +336,7 @@ export async function fetchLogs(scriptId: number): Promise<Log[]> {
export async function addLog(scriptId: number, log: Log): Promise<Log> {
const response = await fetch(`${API_URL}/script/${scriptId}/log`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify(log)
});
if (!response.ok) {
@@ -291,7 +348,8 @@ export async function addLog(scriptId: number, log: Log): Promise<Log> {
// Execute a script by ID
export async function executeScript(scriptId: number): Promise<{ message: string }> {
const response = await fetch(`${API_URL}/script/${scriptId}/execute`, {
method: 'POST'
method: 'POST',
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to execute script');
@@ -302,7 +360,8 @@ export async function executeScript(scriptId: number): Promise<{ message: string
// Delete a log from a specific script
export async function deleteLog(scriptId: number, logId: number): Promise<void> {
const response = await fetch(`${API_URL}/script/${scriptId}/log/${logId}`, {
method: 'DELETE'
method: 'DELETE',
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to delete log');
@@ -313,7 +372,8 @@ export async function deleteLog(scriptId: number, logId: number): Promise<void>
// Delete a script
export async function deleteScript(id: number): Promise<void> {
const response = await fetch(`${API_URL}/script/${id}`, {
method: 'DELETE'
method: 'DELETE',
headers: authHeaders()
});
if (!response.ok) {
throw new Error('Failed to delete script');