mirror of
https://github.com/danbulant/Portfolio
synced 2026-06-08 01:00:16 +00:00
feat: candidate portfolio download
This commit is contained in:
parent
9f35f6fa89
commit
b968279702
3 changed files with 78 additions and 1 deletions
|
|
@ -202,6 +202,17 @@ export const apiSubmitPortfolio = async (): Promise<boolean> => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const apiGetPortfolio = async (): Promise<Blob> => {
|
||||||
|
const res = await fetch(API_URL + '/candidate/portfolio/download', {
|
||||||
|
method: 'GET',
|
||||||
|
credentials: 'include'
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
throw errorHandler(await res.text(), 'Failed to download portfolio');
|
||||||
|
}
|
||||||
|
return await res.blob();
|
||||||
|
};
|
||||||
|
|
||||||
export const apiDeltePortfolio = async (): Promise<boolean> => {
|
export const apiDeltePortfolio = async (): Promise<boolean> => {
|
||||||
try {
|
try {
|
||||||
await axios.post(API_URL + '/candidate/portfolio/delete', {}, { withCredentials: true });
|
await axios.post(API_URL + '/candidate/portfolio/delete', {}, { withCredentials: true });
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import debounce from 'just-debounce-it';
|
import debounce from 'just-debounce-it';
|
||||||
|
|
||||||
import { apiDeltePortfolio, apiSubmitPortfolio } from '$lib/@api/candidate';
|
import { apiDeltePortfolio, apiGetPortfolio, apiSubmitPortfolio } from '$lib/@api/candidate';
|
||||||
import Circles from '$lib/components/icons/Circles.svelte';
|
import Circles from '$lib/components/icons/Circles.svelte';
|
||||||
import { fetchSubmProgress, type Status } from '$lib/stores/portfolio';
|
import { fetchSubmProgress, type Status } from '$lib/stores/portfolio';
|
||||||
import StatusNotificationBig from './StatusNotificationBig.svelte';
|
import StatusNotificationBig from './StatusNotificationBig.svelte';
|
||||||
|
import InfoButton from './InfoButton.svelte';
|
||||||
|
import { candidateData } from '$lib/stores/candidate';
|
||||||
|
|
||||||
export let title: string;
|
export let title: string;
|
||||||
export let status: Status;
|
export let status: Status;
|
||||||
|
|
@ -32,11 +34,32 @@
|
||||||
await deletePortfolio();
|
await deletePortfolio();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const downloadPortfolio = async () => {
|
||||||
|
try {
|
||||||
|
const portfolioBlob = await apiGetPortfolio();
|
||||||
|
const url = window.URL.createObjectURL(new Blob([portfolioBlob]));
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.setAttribute('download', 'PORTFOLIO' + '_' + $candidateData.candidate.name + '_' + $candidateData.candidate.surname + '.zip');
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="card flex flex-col">
|
<div class="card flex flex-col">
|
||||||
<div class="infoBar flex flex-row-reverse">
|
<div class="infoBar flex flex-row-reverse">
|
||||||
<StatusNotificationBig {loading} {status} on:click={debounce(handleNotificationClick, 150)} />
|
<StatusNotificationBig {loading} {status} on:click={debounce(handleNotificationClick, 150)} />
|
||||||
|
<div class="mr-4">
|
||||||
|
<div on:click on:keydown class="flex flex-col">
|
||||||
|
<div class="flex flex-col h-20">
|
||||||
|
<InfoButton on:download={downloadPortfolio}></InfoButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="relative flex flex-row justify-between">
|
<div class="relative flex flex-row justify-between">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
43
frontend/src/lib/components/dashboard/InfoButton.svelte
Normal file
43
frontend/src/lib/components/dashboard/InfoButton.svelte
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { tippy } from 'svelte-tippy';
|
||||||
|
import 'tippy.js/dist/tippy.css';
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
const showInfo = () => {
|
||||||
|
dispatch('showInfo');
|
||||||
|
}
|
||||||
|
|
||||||
|
const download = () => {
|
||||||
|
dispatch('download');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span on:click={(_) => showInfo()} on:keydown={(_) => showInfo()} use:tippy={{
|
||||||
|
content: "Zobrazit osobní údaje",
|
||||||
|
placement: 'top',
|
||||||
|
showOnCreate: false,
|
||||||
|
delay: 0
|
||||||
|
}}>
|
||||||
|
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path></svg>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span on:click={(_) => download()} on:keydown={(_) => download()} use:tippy={{
|
||||||
|
content: "Stáhnout portfolio",
|
||||||
|
placement: 'top',
|
||||||
|
showOnCreate: false,
|
||||||
|
delay: 0
|
||||||
|
}}>
|
||||||
|
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path></svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.icon {
|
||||||
|
@apply w-10 h-10 stroke-sspsBlueDark hover:cursor-pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in a new issue