Преглед на файлове

add standard function for get requests

Daniel Bohry преди 9 месеца
родител
ревизия
40bfff08a5
променени са 4 файла, в които са добавени 143 реда и са изтрити 132 реда
  1. 11 14
      src/routes/insights/+page.svelte
  2. 2 11
      src/routes/portfolio/+page.svelte
  3. 107 107
      src/routes/stocks/+page.svelte
  4. 23 0
      src/utils/api.js

+ 11 - 14
src/routes/insights/+page.svelte

@@ -4,6 +4,7 @@
 	import { authentication } from '../store.js';
 	import { fade } from 'svelte/transition';
 	import { goto } from '$app/navigation';
+	import { getRequest } from '../../utils/api.js';
 
 	let authToken;
 	let data = {};
@@ -20,22 +21,18 @@
 
 	async function fetchPortfolio() {
 		try {
-			const response = await fetch(`${import.meta.env.VITE_STOCKS_HOST}/api/portfolios`, {
-				headers: {
-					Authorization: `Bearer ${authToken}`
-				}
-			});
-
-			if (!response.ok) {
-				const error = await response.json();
-				throw new Error(error.message || 'Unknown error');
-			}
+			const response = await getRequest(`${import.meta.env.VITE_STOCKS_HOST}/api/portfolios`, {}, authToken);
 
-			const portfolio = await response.json();
+			if (response.ok) {
+				const portfolio = await response.json();
 
-			if (portfolio?.length) {
-				data = portfolio[0];
-				data.stocks = data.stocks.sort((a, b) => a.total - b.total);
+				if (portfolio?.length) {
+					data = portfolio[0];
+					data.stocks = data.stocks.sort((a, b) => a.total - b.total);
+				}
+			} else {
+				const error = await response.json();
+				console.error('Failed to find portfolio info:', error);
 			}
 		} catch (error) {
 			console.error('Failed to fetch insights:', error);

+ 2 - 11
src/routes/portfolio/+page.svelte

@@ -3,7 +3,7 @@
 	import { onMount } from 'svelte';
 	import { fade } from 'svelte/transition';
 	import AddStock from '../../components/AddStock.svelte';
-	import { goto } from '$app/navigation';
+	import { getRequest } from '../../utils/api.js';
 
 	let portfolioId = undefined;
 	let result = [];
@@ -30,15 +30,7 @@
 
 	async function fetchPortfolio() {
 		try {
-			const response = await fetch(
-				`${import.meta.env.VITE_STOCKS_HOST}/api/portfolios?currency=${currency}`,
-				{
-					method: 'GET',
-					headers: {
-						Authorization: 'Bearer ' + authToken
-					}
-				}
-			);
+			const response = await getRequest(`${import.meta.env.VITE_STOCKS_HOST}/api/portfolios?currency=${currency}`, {}, authToken);
 
 			if (response.ok) {
 				await update(response.json());
@@ -48,7 +40,6 @@
 			}
 		} catch (err) {
 			console.error('Failed to find portfolio info', err);
-			await goto('/logout');
 		} finally {
 			isLoading = false;
 		}

+ 107 - 107
src/routes/stocks/+page.svelte

@@ -2,6 +2,7 @@
 	import { onMount } from 'svelte';
 	import { fade } from 'svelte/transition';
 	import { goto } from '$app/navigation';
+	import { getRequest } from '../../utils/api.js';
 
 	let result = [];
 	let stockQuery = '';
@@ -19,9 +20,8 @@
 		let query = stock === undefined ? '/api/stocks' : '/api/stocks?q=' + stock;
 
 		try {
-			const response = await fetch(import.meta.env.VITE_STOCKS_HOST + query, {
-				method: 'GET'
-			});
+
+			const response = await getRequest(import.meta.env.VITE_STOCKS_HOST + query, {}, null);
 
 			if (response.ok) {
 				return await response.json();
@@ -87,108 +87,108 @@
 {/if}
 
 <style>
-	.filter-card {
-		margin: 1rem 0;
-		padding: 20px;
-		background-color: #fafafa;
-		border-radius: 12px;
-		box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
-		display: flex;
-		justify-content: center;
-	}
-
-	.input-field {
-		width: 100%;
-		max-width: 100%;
-		padding: 10px 15px;
-		font-size: 1rem;
-		border: 1px solid #ddd;
-		border-radius: 8px;
-		outline: none;
-		transition: box-shadow 0.2s;
-	}
-
-	.input-field:focus {
-		box-shadow: 0 0 0 2px #27ae60;
-		border-color: #27ae60;
-	}
-
-	.result {
-		display: flex;
-		flex-wrap: wrap;
-		gap: 2rem;
-		justify-content: center;
-		padding-bottom: 2rem;
-	}
-
-	.card {
-		background-color: #fafafa;
-		border: 1px solid #eee;
-		border-radius: 12px;
-		width: 275px;
-		height: 115px;
-		padding: 1rem;
-		box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
-		transition: transform 0.2s ease;
-		display: flex;
-		flex-direction: column;
-		justify-content: space-between;
-	}
-
-	.card:hover {
-		transform: translateY(-8px);
-	}
-
-	.stock-info {
-		display: flex;
-		justify-content: space-between;
-		align-items: center;
-		margin-bottom: 10px;
-	}
-
-	.stock-code {
-		font-size: 1.5rem;
-		font-weight: bold;
-		color: #333;
-	}
-
-	.stock-name {
-		font-size: 1.1rem;
-		color: #555;
-		text-align: right;
-	}
-
-	.stock-info:after {
-		content: '';
-		display: block;
-		width: 100%;
-		height: 1px;
-		background-color: #ddd;
-		margin-top: 10px;
-	}
-
-	.stock-details {
-		display: flex;
-		justify-content: space-between;
-		align-items: center;
-		margin-top: 15px;
-	}
-
-	.stock-currency {
-		font-size: 1rem;
-		color: #888;
-	}
-
-	.stock-price {
-		font-size: 1.5rem;
-		font-weight: bold;
-		color: #27ae60;
-	}
-
-	p {
-		text-align: center;
-		color: #999;
-		font-size: 1rem;
-		margin-top: 2rem;
-	}
+    .filter-card {
+        margin: 1rem 0;
+        padding: 20px;
+        background-color: #fafafa;
+        border-radius: 12px;
+        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
+        display: flex;
+        justify-content: center;
+    }
+
+    .input-field {
+        width: 100%;
+        max-width: 100%;
+        padding: 10px 15px;
+        font-size: 1rem;
+        border: 1px solid #ddd;
+        border-radius: 8px;
+        outline: none;
+        transition: box-shadow 0.2s;
+    }
+
+    .input-field:focus {
+        box-shadow: 0 0 0 2px #27ae60;
+        border-color: #27ae60;
+    }
+
+    .result {
+        display: flex;
+        flex-wrap: wrap;
+        gap: 2rem;
+        justify-content: center;
+        padding-bottom: 2rem;
+    }
+
+    .card {
+        background-color: #fafafa;
+        border: 1px solid #eee;
+        border-radius: 12px;
+        width: 275px;
+        height: 115px;
+        padding: 1rem;
+        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
+        transition: transform 0.2s ease;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+    }
+
+    .card:hover {
+        transform: translateY(-8px);
+    }
+
+    .stock-info {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 10px;
+    }
+
+    .stock-code {
+        font-size: 1.5rem;
+        font-weight: bold;
+        color: #333;
+    }
+
+    .stock-name {
+        font-size: 1.1rem;
+        color: #555;
+        text-align: right;
+    }
+
+    .stock-info:after {
+        content: '';
+        display: block;
+        width: 100%;
+        height: 1px;
+        background-color: #ddd;
+        margin-top: 10px;
+    }
+
+    .stock-details {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-top: 15px;
+    }
+
+    .stock-currency {
+        font-size: 1rem;
+        color: #888;
+    }
+
+    .stock-price {
+        font-size: 1.5rem;
+        font-weight: bold;
+        color: #27ae60;
+    }
+
+    p {
+        text-align: center;
+        color: #999;
+        font-size: 1rem;
+        margin-top: 2rem;
+    }
 </style>

+ 23 - 0
src/utils/api.js

@@ -0,0 +1,23 @@
+import { goto } from '$app/navigation';
+
+export async function getRequest(url, options = {}, token) {
+	const headers = token !== null
+		? {
+			...options.headers,
+			Authorization: `Bearer ${token}`
+		}
+		: {
+			...options.headers
+		};
+
+	const response = await fetch(url, {
+		...options,
+		headers
+	});
+
+	if (response.status === 401) {
+		await goto('/logout');
+	}
+
+	return response;
+}