diff --git a/.dockerignore b/.dockerignore index af098af..e4ee886 100644 --- a/.dockerignore +++ b/.dockerignore @@ -6,6 +6,7 @@ node_modules .git .gitattributes +.gitea .eslintignore .eslintrc.cjs diff --git a/src/app.html b/src/app.html index a664528..bfd3cb5 100644 --- a/src/app.html +++ b/src/app.html @@ -95,6 +95,20 @@ box-shadow: .3em .3em .3em var(--header); } + .container { + max-width: 90%; + margin: auto; + } + + .cards { + display: flex; + flex-wrap: wrap; + flex-direction: row; + gap: 3em 3em; + padding: 2em 0em 2em 0em; + transition: all 0.2s; + } + @keyframes animationName { 0% { opacity:0; } 50% { opacity:1; } diff --git a/src/lib/api/git.ts b/src/lib/api/git.ts new file mode 100644 index 0000000..cdef558 --- /dev/null +++ b/src/lib/api/git.ts @@ -0,0 +1,49 @@ +import type { GitRepo } from "../types"; + +const API_BASE_URL = "https://git.luke-else.co.uk/api/v1"; + + +export async function fetchRepos(): Promise { + try { + console.log("Fetching repos..."); + const response = await fetch(`${API_BASE_URL}/repos/search?sort=updated&order=desc&limit=12`, { + headers: { + // "Authorization": `token ${ACCESS_TOKEN}`, + "Content-Type": "application/json" + } + }); + + if (!response.ok) { + throw new Error(`Error: ${response.statusText}`); + } + + const data: { data: GitRepo[] } = await response.json(); + return data.data; // Extract the list of repositories + } catch (error) { + console.error("Failed to fetch repos:", error); + return []; + } +} + +export function timeSince(inputDate: Date | string): string { + const date = new Date(inputDate); // Ensure it's a Date object + if (isNaN(date.getTime())) { + throw new Error("Invalid date provided"); + } + + const now: Date = new Date(); + const diffInMs: number = now.getTime() - date.getTime(); + const diffInSeconds: number = Math.floor(diffInMs / 1000); + const diffInMinutes: number = Math.floor(diffInSeconds / 60); + const diffInHours: number = Math.floor(diffInMinutes / 60); + const diffInDays: number = Math.floor(diffInHours / 24); + const diffInMonths: number = Math.floor(diffInDays / 30); // Approximate + const diffInYears: number = Math.floor(diffInDays / 365); // Approximate + + if (diffInDays === 0) return "Today"; + if (diffInDays === 1) return "Yesterday"; + if (diffInDays < 7) return `${diffInDays} days ago`; + if (diffInDays < 30) return `${Math.floor(diffInDays / 7)} week${diffInDays >= 14 ? 's' : ''} ago`; + if (diffInMonths < 12) return `${diffInMonths} month${diffInMonths > 1 ? 's' : ''} ago`; + return `${diffInYears} year${diffInYears > 1 ? 's' : ''} ago`; +} \ No newline at end of file diff --git a/src/lib/components/Cards/Card.svelte b/src/lib/components/Cards/Card.svelte index c5f4ab9..d13957c 100644 --- a/src/lib/components/Cards/Card.svelte +++ b/src/lib/components/Cards/Card.svelte @@ -20,7 +20,9 @@ border-radius: .5em; scroll-snap-align: start; transition: all 0.2s; + box-shadow: .25em .25em .5em var(--hover); } + .card:hover { box-shadow: .5em .5em .5em var(--hover); } diff --git a/src/lib/components/Toasts/Toasts.svelte b/src/lib/components/Toasts/Toasts.svelte index 3977df4..5a0bc71 100644 --- a/src/lib/components/Toasts/Toasts.svelte +++ b/src/lib/components/Toasts/Toasts.svelte @@ -1,7 +1,7 @@ {#if $toasts} diff --git a/src/lib/store.ts b/src/lib/stores.ts similarity index 68% rename from src/lib/store.ts rename to src/lib/stores.ts index 9d46f52..41f1da4 100644 --- a/src/lib/store.ts +++ b/src/lib/stores.ts @@ -1,6 +1,12 @@ import { ToastType, type Toast } from "$lib/toast"; import { writable, type Writable } from "svelte/store"; +import type { GitRepo } from "./types"; +import { fetchRepos } from "./api/git"; + +//////////////////////////////////////// +// Toast Stores +//////////////////////////////////////// export const toasts: Writable = writable([]); export const addToast = (toast: Toast) => { @@ -25,4 +31,13 @@ export const addToast = (toast: Toast) => { export const dismissToast = (id: number) => { toasts.update((all) => all.filter((t) => t.id !== id)); -}; \ No newline at end of file +}; + +//////////////////////////////////////// +// Git Repo Stores +//////////////////////////////////////// +export const repos = writable([]); + +export async function loadRepos() { + repos.set(await fetchRepos()); +} \ No newline at end of file diff --git a/src/lib/types.ts b/src/lib/types.ts new file mode 100644 index 0000000..881c386 --- /dev/null +++ b/src/lib/types.ts @@ -0,0 +1,14 @@ +export interface GitRepo { + name: string; + description: string; + language: string; + size: number; + updated_at: Date; + html_url: string; + private: boolean; + fork: boolean; + owner: { + login: string; + avatar_url: string; + }; +} \ No newline at end of file diff --git a/src/main.svelte b/src/main.svelte index 5b3f3ff..ef2b849 100644 --- a/src/main.svelte +++ b/src/main.svelte @@ -1,7 +1,7 @@ + +

My Projects

+

This here is a list of my most recently worked on projects. Note this does not show any private repositories. For more in depth information Click Here.

+ +
+ {#if $repos.length > 0} +
{addToast(new Toast("See a snapshot of my latest work.", ToastType.Info, true, 8_000))}
+
+ {#each $repos as repo} + +
+

{repo.name}

+ {repo.language} +
+
+

{@html repo.description}

+
+
+ + {repo.name} + {timeSince(repo.updated_at)} +
+
+ {/each} +
+ {:else} +

Loading repositories...

+ {/if} +
diff --git a/static/json/me.json b/static/json/me.json index 1ac2375..df11f9d 100644 --- a/static/json/me.json +++ b/static/json/me.json @@ -44,7 +44,12 @@ { "duration" : "September 2022 - Present", "title" : "Thales UK - Software Engineer", - "description" : "As a software engineering apprentice at Thales UK, I find myself partaking in agile / scrum development methodologies in a strong team of 6 other engineers. The team iterates on a pre-existing system designed for the MOD, written in C++, using internal frameworks to assist.

To extend this, the apprenticeship includes allocated time for studying a Digital and Thechnology Solutions degree with the University of Warwick, including modules relevant to business management, devlopment processes and data integrity etc..." + "description" : "As a software engineering apprentice at Thales UK, I find myself partaking in agile / scrum development methodologies in a strong team of 6 other engineers. The team iterates on a pre-existing system designed for the MOD, written in C++, using internal frameworks to assist." + }, + { + "duration" : "September 2022 - Present", + "title" : "University of Warwick - Digital and Technology Solutions", + "description" : "The apprenticeship includes allocated time for studying a Digital and Thechnology Solutions degree with the University of Warwick, including modules relevant to business management, devlopment processes and data integrity etc..." }, { "duration" : "September 2020 - July 2022", @@ -54,7 +59,7 @@ { "duration" : "September 2015 - July 2020", "title" : "The Norton Knatchbull School (GCSEs)", - "description" : "FSMQ (C)
Maths (8)
Geography (9)
Biology (9)
Chemistry (9)
Physics (9)
Spanish (7)
English (Literature & Language) (7, 7)
Computer Science (9)" + "description" : "Computer Science (9)
Physics (9)
Chemistry (9)
Biology (9)
Geography (9)
FSMQ (C)
Maths (8)
Spanish (7)
English (Literature & Language) (7, 7)
" } ] } \ No newline at end of file