Basically, I have an initial load from an external API but if the user decides to change the start date and end date then it’s supposed to query the external API again with updated parameters and load to the frontend.
This is my +page.server.ts:
import { auth } from '$lib/server/lucia';
import { fail, redirect } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ locals }) => {
const session = await locals.auth.validate();
if (!session) throw redirect(302, '/login');
const today = new Date().toISOString().slice(0, 10);
const fetchTtlSales = async (startDate = today, endDate = today) => {
const res = await fetch(
`https://www.externalapi.com/api/rpts/ttl?startDate=${startDate}&endDate=${endDate}`
);
const data = await res.json();
return data[0];
};
const fetchDeptSales = async (startDate = today, endDate = today) => {
const res = await fetch(
`https://www.externalapi.com/api/rpts/dpt?startDate=${startDate}&endDate=${endDate}`
);
const data = await res.json();
return data;
};
const fetchTenders = async (startDate = today, endDate = today) => {
const res = await fetch(
`https://www.externalapi.com/api/rpts/tnd?startDate=${startDate}&endDate=${endDate}`
);
const data = await res.json();
return data;
};
const fetchTax = async (startDate = today, endDate = today) => {
const results = [];
for (let i = 1; i < 4; i++) {
const res = await fetch(
`https://www.externalapi.com/api/rpts/tax${i}?startDate=${startDate}&endDate=${endDate}`
);
const data = await res.json();
results.push(data);
}
return results;
};
const fetchPropDisc = async (startDate = today, endDate = today) => {
const res = await fetch(
`https://www.externalapi.com/api/rpts/prodisc?startDate=${startDate}&endDate=${endDate}`
);
const data = await res.json();
return data;
};
const ttlSales = await fetchTtlSales(); // Await the result here
const dptSales = await fetchDeptSales();
const tndTtls = await fetchTenders();
const taxTtls = await fetchTax();
const propDisc = await fetchPropDisc();
return {
name: session.user.name,
ttlSales: ttlSales,
dptSales: dptSales,
tndTtls: tndTtls,
taxTtls: taxTtls,
propDisc: propDisc
};
};
export const actions: Actions = {
logout: async ({ locals }) => {
const session = await locals.auth.validate();
if (!session) return fail(401);
await auth.invalidateAllUserSessions(session.sessionId); // invalidate session
locals.auth.setSession(null); // remove cookie
throw redirect(302, '/login'); // redirect to login page
},
refresh: async ({ request, locals }) => {
const session = await locals.auth.validate();
if (!session) throw redirect(302, '/login');
const { startDate, endDate } = Object.fromEntries(await request.formData()) as {
startDate: string;
endDate: string;
};
try {
const fetchTtlSales = async () => {
const res = await fetch(
`https://www.externalapi.com/api/rpts/ttl?startDate=${startDate}&endDate=${endDate}`
);
const data = await res.json();
return data[0];
};
const fetchDeptSales = async () => {
const res = await fetch(
`https://www.externalapi.com/api/rpts/dpt?startDate=${startDate}&endDate=${endDate}`
);
const data = await res.json();
return data;
};
const fetchTenders = async () => {
const res = await fetch(
`https://www.externalapi.com/api/rpts/tnd?startDate=${startDate}&endDate=${endDate}`
);
const data = await res.json();
return data;
};
const fetchTax = async () => {
const results = [];
for (let i = 1; i < 4; i++) {
const res = await fetch(
`https://www.externalapi.com/api/rpts/tax${i}?startDate=${startDate}&endDate=${endDate}`
);
const data = await res.json();
results.push(data);
}
return results;
};
const fetchPropDisc = async () => {
const res = await fetch(
`https://www.externalapi.com/api/rpts/prodisc?startDate=${startDate}&endDate=${endDate}`
);
const data = await res.json();
return data;
};
const ttlSales = await fetchTtlSales(); // Await the result here
const dptSales = await fetchDeptSales();
const tndTtls = await fetchTenders();
const taxTtls = await fetchTax();
const propDisc = await fetchPropDisc();
return {
ttlSales: ttlSales,
dptSales: dptSales,
tndTtls: tndTtls,
taxTtls: taxTtls,
propDisc: propDisc
};
} catch (err) {
console.error(err);
return fail(500, { message: 'Could not get data' });
}
}
};
This is my +page.svelte:
<script lang="ts">
// @ts-nocheck
import Navbar from '$lib/components/Navbar.svelte';
import { enhance } from '$app/forms';
export let data;
$: ({ name, ttlSales, dptSales, tndTtls, taxTtls, propDisc } = data);
const today = new Date().toISOString().slice(0, 10);
let startDate = today;
let endDate = today;
/* async function reload(event) {
event.preventDefault();
await goto(`/sales?startDate=${startDate}&endDate=${endDate}`);
} */
$: totalDptSum = data.dptSales.reduce((ttl, eachTtl) => ttl + eachTtl.TOTAL, 0).toFixed(2);
$: totalTndSum = data.tndTtls.reduce((ttl, eachTtl) => ttl + eachTtl.TOTAL, 0).toFixed(2);
/* const Tax1 = taxTtls
.map((ttl) => ttl[0].TAX_1) // Get an array with possibly undefined values
.filter((value) => typeof value === 'number') // Filter out undefined values
.map((value) => value.toFixed(2)); // Format numbers to fixed 2 decimal places as strings
const Tax2 = taxTtls
.map((ttl) => ttl[0].TAX_2)
.filter((value) => typeof value === 'number')
.map((value) => value.toFixed(2));
const Tax3 = taxTtls
.map((ttl) => ttl[0].TAX_3)
.filter((value) => typeof value === 'number')
.map((value) => value.toFixed(2));
$: totaltaxSum = parseFloat(Tax1) + parseFloat(Tax2) + parseFloat(Tax3); */
</script>
<body>
<main class="container">
<h1 class="noMarginBottom">
Welcome, {name}!
</h1>
<Navbar />
<form method="post" action="?/refresh" use:enhance>
<p>Start date:</p>
<input type="date" id="start" name="startDate" bind:value={startDate} />
<p>End date:</p>
<input type="date" id="start" name="endDate" bind:value={endDate} />
<button class="searchButton" type="submit">Search</button>
</form>
<details open>
<!-- svelte-ignore a11y-no-redundant-roles -->
<summary role="button" class="contrast">Total Sales</summary>
<h1>${ttlSales.TOTAL ? ttlSales.TOTAL : '0.00'}</h1>
</details>
<details open>
<!-- svelte-ignore a11y-no-redundant-roles -->
<summary role="button" class="contrast">Department Sales</summary>
<table>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Amount</th>
</tr>
</thead>
<tbody>
{#each dptSales as sale}
<tr>
<td>{sale.F238 ? sale.F238 : 'N/A'}</td>
<td>${sale.TOTAL ? sale.TOTAL : '0.00'}</td>
</tr>
{/each}
</tbody>
<tfoot>
<tr>
<td scope="col"></td>
<td scope="col" style="color:chartreuse">${totalDptSum ? totalDptSum : '0.00'}</td>
</tr>
</tfoot>
</table>
</details>
<details open>
<summary role="button" class="contrast">Tenders</summary>
<table>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Amount</th>
</tr>
</thead>
<tbody>
{#each tndTtls as tender}
<tr>
<td>{tender.F1039 ? tender.F1039 : 'N/A'}</td>
<td>${tender.TOTAL ? tender.TOTAL : '0.00'}</td>
</tr>
{/each}
</tbody>
<tfoot>
<tr>
<td scope="col"></td>
<td scope="col" style="color:chartreuse">${totalTndSum ? totalTndSum : '0.00'}</td>
</tr>
</tfoot>
</table>
</details>
<details open>
<summary role="button" class="contrast">Taxes</summary>
<table>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tax 1</td>
<!-- <td>${Tax1 ? Tax1 : '0.00'}</td> -->
</tr>
<tr>
<td>Tax 2</td>
<!-- <td>${Tax2 ? Tax2 : '0.00'}</td> -->
</tr>
<tr>
<td>Tax 3</td>
<!-- <td>${Tax3 ? Tax3 : '0.00'}</td> -->
</tr>
</tbody>
<tfoot>
<tr>
<td scope="col"></td>
<!-- <td scope="col" style="color:chartreuse">${totaltaxSum}</td> -->
</tr>
</tfoot>
</table>
</details>
<details open>
<summary role="button" class="contrast">Discounts</summary>
<table>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>Proportional Disc.</td>
<td>$10.00</td>
</tr>
<tr>
<td>Global Disc.</td>
<td>$20.00</td>
</tr>
</tbody>
<tfoot>
<tr>
<td scope="col"></td>
<td scope="col" style="color:chartreuse">$30.00</td>
</tr>
</tfoot>
</table>
</details>
<button class="download-excel">Excel</button>
<button class="download-pdf">PDF</button>
</main>
</body>
<style>
details h1 {
text-align: center;
font-size: 300%;
}
.noMarginBottom {
margin-bottom: 0px;
}
.searchButton {
background-color: coral;
border-color: coral;
}
.download-excel {
background-color: green;
border-color: green;
}
.download-pdf {
background-color: crimson;
border-color: crimson;
}
</style>
I was looking at invalidate() function to refresh the load, but then it would reload my whole page and reset my startDate and endDate inputs back to the current date even though I had changed it to another date. I found that the invalidate() function takes away from the whole “single page app” concept.
I’m looking for the best way to do this and right now I don’t think I’m on the right track because I’m being redundant calling the API in my load function as well as in a named action.
Help would be greatly appreciate it š