your personal website on atproto - mirror
blento.app
1<script lang="ts">
2 import { onMount } from 'svelte';
3 import { siGithub } from 'simple-icons';
4 import { getAdditionalUserData } from '$lib/website/context';
5 import type { ContentComponentProps } from '../../types';
6 import type { GithubProfileLoadedData } from '.';
7 import GithubContributionsGraph from './GithubContributionsGraph.svelte';
8 import { Button } from '@foxui/core';
9 import { browser } from '$app/environment';
10 import { qrOverlay } from '$lib/components/qr/qrOverlay.svelte';
11 import { fetchGitHubContributions } from './api.remote';
12
13 let { item, isEditing }: ContentComponentProps = $props();
14
15 const githubUrl = $derived(`https://github.com/${item.cardData.user}`);
16
17 const data = getAdditionalUserData();
18
19 // svelte-ignore state_referenced_locally
20 let contributionsData = $state(
21 (data[item.cardType] as GithubProfileLoadedData)?.[item.cardData.user]
22 );
23
24 onMount(async () => {
25 if (!contributionsData && item.cardData?.user) {
26 try {
27 contributionsData = await fetchGitHubContributions(item.cardData.user);
28 if (contributionsData) {
29 data[item.cardType] ??= {};
30 (data[item.cardType] as GithubProfileLoadedData)[item.cardData.user] = contributionsData;
31 }
32 } catch (error) {
33 console.error('Failed to fetch GitHub contributions:', error);
34 }
35 }
36 });
37</script>
38
39<div class="github-profile-card h-full overflow-hidden p-4">
40 <div class="flex h-full flex-col justify-between">
41 <!-- Header -->
42 <div class="flex justify-between">
43 <div class="flex items-center gap-3">
44 <div class="fill-base-950 size-6 shrink-0 dark:fill-white [&_svg]:size-full">
45 {@html siGithub.svg}
46 </div>
47 <a
48 href="https://github.com/{item.cardData.user}"
49 target="_blank"
50 rel="noopener noreferrer"
51 class=" flex truncate text-2xl font-bold transition-colors"
52 >
53 {item.cardData.user}
54 </a>
55 </div>
56
57 <div class="github-follow z-50">
58 <Button
59 href="https://github.com/{item.cardData.user}"
60 target="_blank"
61 rel="noopener noreferrer">Follow</Button
62 >
63 </div>
64 </div>
65
66 {#if contributionsData && browser}
67 <div class="flex opacity-100 transition-opacity duration-300 starting:opacity-0">
68 <div class="github-graph github-graph-compact">
69 <GithubContributionsGraph data={contributionsData} isBig={false} />
70 </div>
71 <div class="github-graph github-graph-expanded">
72 <GithubContributionsGraph data={contributionsData} isBig={true} />
73 </div>
74 </div>
75 {/if}
76 </div>
77</div>
78
79{#if (item.cardData.href || item.cardData.user) && !isEditing}
80 <a
81 href={item.cardData.href || githubUrl}
82 class="absolute inset-0 h-full w-full"
83 target="_blank"
84 rel="noopener noreferrer"
85 use:qrOverlay={{
86 context: {
87 title: item.cardData.user,
88 icon: siGithub.svg,
89 iconColor: siGithub.hex
90 }
91 }}
92 >
93 <span class="sr-only">Show on github</span>
94 </a>
95{/if}
96
97<style>
98 .github-follow,
99 .github-graph-expanded {
100 display: none;
101 }
102
103 .github-graph-compact {
104 display: flex;
105 width: 100%;
106 }
107
108 @container card (width >= 18rem) {
109 .github-follow {
110 display: inline-flex;
111 }
112 }
113
114 @container card (height >= 12rem) {
115 .github-graph-compact {
116 display: none;
117 }
118
119 .github-graph-expanded {
120 display: flex;
121 width: 100%;
122 }
123 }
124</style>