feat: front end first pass

This commit is contained in:
EDRipper 2025-12-07 02:38:40 -05:00
parent 524d89573c
commit 3693c59a20
24 changed files with 1211 additions and 12 deletions

10
backend/.env.example Normal file
View file

@ -0,0 +1,10 @@
AIRTABLE_PAT=dummy
AIRTABLE_BASE=dummy
SESSION_SECRET=dummy
OIDC_ISSUER=dummy
OIDC_CLIENT_ID=dummy
OIDC_CLIENT_SECRET=dummy
OIDC_REDIRECT_URI=dummy
HACKATIME_CLIENT_ID=dummy
HACKATIME_CLIENT_SECRET=dummy
HACKATIME_REDIRECT_URI=dummy

4
backend/.gitignore vendored
View file

@ -1 +1,3 @@
.env
.env
.env.*
!.env.example

31
package-lock.json generated
View file

@ -8,6 +8,7 @@
"name": "stickers",
"version": "0.0.1",
"dependencies": {
"bootstrap": "^5.3.8",
"flubber": "^0.4.2"
},
"devDependencies": {
@ -519,6 +520,17 @@
"dev": true,
"license": "MIT"
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"license": "MIT",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz",
@ -979,6 +991,25 @@
"node": ">= 0.4"
}
},
"node_modules/bootstrap": {
"version": "5.3.8",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz",
"integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"license": "MIT",
"peerDependencies": {
"@popperjs/core": "^2.11.8"
}
},
"node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",

View file

@ -21,6 +21,7 @@
"vite": "^7.2.2"
},
"dependencies": {
"bootstrap": "^5.3.8",
"flubber": "^0.4.2"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 KiB

View file

@ -0,0 +1,551 @@
.bg-image-8 {
position: absolute;
width: 604px;
height: 616px;
background: url('./backgrounds-assets/image%208.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(16.1deg);
}
.bg-image-2 {
position: absolute;
width: 831px;
height: 512px;
background: url('./backgrounds-assets/image%202.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-1 {
position: absolute;
width: 492px;
height: 616px;
background: url('./backgrounds-assets/image%201.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-3 {
position: absolute;
width: 704px;
height: 377px;
background: url('./backgrounds-assets/image%203.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(10.07deg);
}
.bg-image-4 {
position: absolute;
width: 500px;
height: 616px;
background: url('./backgrounds-assets/image%204.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-5 {
position: absolute;
width: 467px;
height: 596px;
background: url('./backgrounds-assets/image%205.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(-6.94deg);
}
.bg-image-10 {
position: absolute;
width: 474px;
height: 528px;
background: url('./backgrounds-assets/image%2010.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-14 {
position: absolute;
width: 639px;
height: 439px;
background: url('./backgrounds-assets/image%2014.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(-13.19deg);
}
.bg-image-15 {
position: absolute;
width: 788px;
height: 788px;
background: url('./backgrounds-assets/image%2015.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-16 {
position: absolute;
width: 978px;
height: 1304px;
background: url('./backgrounds-assets/image%2016.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-17 {
position: absolute;
width: 1029.07px;
height: 1455.63px;
background: url('./backgrounds-assets/image%2017.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(3.69deg);
}
.bg-image-18 {
position: absolute;
width: 571.25px;
height: 856.88px;
background: url('./backgrounds-assets/image%2018.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(6.2deg);
}
.bg-image-20 {
position: absolute;
width: 604px;
height: 616px;
background: url('./backgrounds-assets/image%2020.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(16.1deg);
}
.bg-image-21 {
position: absolute;
width: 831px;
height: 512px;
background: url('./backgrounds-assets/image%2021.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-22 {
position: absolute;
width: 492px;
height: 616px;
background: url('./backgrounds-assets/image%2022.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-23 {
position: absolute;
width: 704px;
height: 377px;
background: url('./backgrounds-assets/image%2023.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(10.07deg);
}
.bg-image-29 {
position: absolute;
width: 474px;
height: 528px;
background: url('./backgrounds-assets/image%2029.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-31 {
position: absolute;
width: 639px;
height: 439px;
background: url('./backgrounds-assets/image%2031.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(-13.19deg);
}
.bg-image-33 {
position: absolute;
width: 978px;
height: 1304px;
background: url('./backgrounds-assets/image%2033.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-34 {
position: absolute;
width: 1029.07px;
height: 1455.63px;
background: url('./backgrounds-assets/image%2034.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(3.69deg);
}
.bg-image-35 {
position: absolute;
width: 571.25px;
height: 856.88px;
background: url('./backgrounds-assets/image%2035.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(6.2deg);
}
.bg-image-37 {
position: absolute;
width: 604px;
height: 616px;
background: url('./backgrounds-assets/image%2037.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(16.1deg);
}
.bg-image-38 {
position: absolute;
width: 831px;
height: 512px;
background: url('./backgrounds-assets/image%2038.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-39 {
position: absolute;
width: 492px;
height: 616px;
background: url('./backgrounds-assets/image%2039.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-40 {
position: absolute;
width: 704px;
height: 377px;
background: url('./backgrounds-assets/image%2040.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(10.07deg);
}
.bg-image-41 {
position: absolute;
width: 500px;
height: 616px;
background: url('./backgrounds-assets/image%2041.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-42 {
position: absolute;
width: 760px;
height: 664px;
background: url('./backgrounds-assets/image%2042.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-43 {
position: absolute;
width: 467px;
height: 596px;
background: url('./backgrounds-assets/image%2043.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(-6.94deg);
}
.bg-image-44 {
position: absolute;
width: 616px;
height: 540px;
background: url('./backgrounds-assets/image%2044.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-46 {
position: absolute;
width: 474px;
height: 528px;
background: url('./backgrounds-assets/image%2046.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-47 {
position: absolute;
width: 639px;
height: 439px;
background: url('./backgrounds-assets/image%2047.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-48 {
position: absolute;
width: 639px;
height: 439px;
background: url('./backgrounds-assets/image%2048.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(-13.19deg);
}
.bg-image-49 {
position: absolute;
width: 788px;
height: 788px;
background: url('./backgrounds-assets/image%2049.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-50 {
position: absolute;
width: 978px;
height: 1304px;
background: url('./backgrounds-assets/image%2050.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-51 {
position: absolute;
width: 1029.07px;
height: 1455.63px;
background: url('./backgrounds-assets/image%2051.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(3.69deg);
}
.bg-image-53 {
position: absolute;
width: 989px;
height: 1399px;
background: url('./backgrounds-assets/image%2053.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-54 {
position: absolute;
width: 604px;
height: 616px;
background: url('./backgrounds-assets/image%2054.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(16.1deg);
}
.bg-image-55 {
position: absolute;
width: 831px;
height: 512px;
background: url('./backgrounds-assets/image%2055.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-56 {
position: absolute;
width: 492px;
height: 616px;
background: url('./backgrounds-assets/image%2056.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-57 {
position: absolute;
width: 704px;
height: 377px;
background: url('./backgrounds-assets/image%2057.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(10.07deg);
}
.bg-image-58 {
position: absolute;
width: 500px;
height: 616px;
background: url('./backgrounds-assets/image%2058.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-59 {
position: absolute;
width: 760px;
height: 664px;
background: url('./backgrounds-assets/image%2059.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-60 {
position: absolute;
width: 467px;
height: 596px;
background: url('./backgrounds-assets/image%2060.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(-6.94deg);
}
.bg-image-61 {
position: absolute;
width: 616px;
height: 540px;
background: url('./backgrounds-assets/image%2061.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-62 {
position: absolute;
width: 557px;
height: 557px;
background: url('./backgrounds-assets/image%2062.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-63 {
position: absolute;
width: 474px;
height: 528px;
background: url('./backgrounds-assets/image%2063.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-64 {
position: absolute;
width: 639px;
height: 439px;
background: url('./backgrounds-assets/image%2064.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-65 {
position: absolute;
width: 639px;
height: 439px;
background: url('./backgrounds-assets/image%2065.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(-13.19deg);
}
.bg-image-66 {
position: absolute;
width: 788px;
height: 788px;
background: url('./backgrounds-assets/image%2066.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-67 {
position: absolute;
width: 978px;
height: 1304px;
background: url('./backgrounds-assets/image%2067.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}
.bg-image-68 {
position: absolute;
width: 1029.07px;
height: 1455.63px;
background: url('./backgrounds-assets/image%2068.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(3.69deg);
}
.bg-image-69 {
position: absolute;
width: 571.25px;
height: 856.88px;
background: url('./backgrounds-assets/image%2069.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
transform: rotate(6.2deg);
}
.bg-image-70 {
position: absolute;
width: 989px;
height: 1399px;
background: url('./backgrounds-assets/image%2070.svg');
background-size: contain;
background-repeat: no-repeat;
filter: drop-shadow(10px 10px 4px #000000);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View file

@ -0,0 +1,66 @@
<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="256" height="256">
<path fill-rule="evenodd" clip-rule="evenodd" d="M128 256C230.4 256 256 230.4 256 128C256 25.6 230.4 0 128 0C25.6 0 0 25.6 0 128C0 230.4 25.6 256 128 256Z" fill="black"/>
</mask>
<g mask="url(#mask0)">
<g filter="url(#filter0_ii)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M128 256C230.4 256 256 230.4 256 128C256 25.6 230.4 0 128 0C25.6 0 0 25.6 0 128C0 230.4 25.6 256 128 256Z" fill="url(#paint0_radial)"/>
</g>
<g filter="url(#filter1_ddii)">
<path d="M115.103 48.3682C115.103 47.1299 113.989 46.1892 112.769 46.3965L81.6652 51.6777C80.7036 51.8409 80 52.6741 80 53.6494V205.085C80 206.189 80.8954 207.085 82 207.085H113.103C114.208 207.085 115.103 206.189 115.103 205.085V148.397C115.103 131.127 124.261 120.429 131.892 120.429C138.76 120.429 140.744 127.307 140.744 137.699V205.085C140.744 206.189 141.639 207.085 142.744 207.085H174C175.105 207.085 176 206.189 176 205.085V132.656C176 109.12 167.148 93.9892 144.102 93.9892C134.852 93.9892 125.825 96.2163 118.633 101.146C117.205 102.125 115.103 101.161 115.103 99.4284V48.3682Z" fill="white"/>
</g>
</g>
</g>
<defs>
<filter id="filter0_ii" x="-6" y="-6" width="268" height="268" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="6" dy="6"/>
<feGaussianBlur stdDeviation="4"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.2 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-6" dy="-6"/>
<feGaussianBlur stdDeviation="4"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"/>
<feBlend mode="normal" in2="effect1_innerShadow" result="effect2_innerShadow"/>
</filter>
<filter id="filter1_ddii" x="64" y="42.3677" width="128" height="192.717" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="12"/>
<feGaussianBlur stdDeviation="8"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="4"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.125 0"/>
<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-2"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.125 0"/>
<feBlend mode="normal" in2="shape" result="effect3_innerShadow"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-2"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.92549 0 0 0 0 0.215686 0 0 0 0 0.313726 0 0 0 0.5 0"/>
<feBlend mode="normal" in2="effect3_innerShadow" result="effect4_innerShadow"/>
</filter>
<radialGradient id="paint0_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="rotate(58.6367) scale(245.935)">
<stop stop-color="#FF8C37"/>
<stop offset="1" stop-color="#EC3750"/>
</radialGradient>
<clipPath id="clip0">
<rect width="256" height="256" fill="white" transform="translate(256) rotate(90)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

View file

@ -0,0 +1,31 @@
<script>
import backPng from '$lib/assets/images/back.png';
</script>
<div class="background-container" style="background-image: url({backPng});">
<div class="overlay"></div>
</div>
<style>
.background-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
background-color: #eeeeee;
background-repeat: repeat;
background-size: auto;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(200, 220, 240, 0.7);
pointer-events: none;
}
</style>

View file

@ -0,0 +1,46 @@
<script>
import hackClubLogo from '$lib/assets/images/hackClubLogo.svg';
export let active = '';
</script>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/dash">
<img src={hackClubLogo} alt="Hack Club Logo" style="height: 40px;">
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item" class:active={active === 'dash'}>
<a class="nav-link" href="/dash">| Home |</a>
</li>
<li class="nav-item" class:active={active === 'trade'}>
<a class="nav-link" href="/trade">Trade |</a>
</li>
<li class="nav-item" class:active={active === 'earn'}>
<a class="nav-link" href="/earn">Earn |</a>
</li>
<li class="nav-item" class:active={active === 'leaderboard'}>
<a class="nav-link" href="/leaderboard">Leaderboard |</a>
</li>
</ul>
</div>
</nav>
<style>
.navbar {
font-family: 'Departure Mono', monospace;
padding: 1rem 2rem;
}
.navbar :global(.nav-link) {
font-size: 1.25rem;
padding: 0.75rem 1.25rem;
}
.navbar :global(.navbar-brand img) {
height: 50px;
}
</style>

17
src/lib/styles/global.css Normal file
View file

@ -0,0 +1,17 @@
@font-face {
font-family: 'Departure Mono';
src: url('$lib/assets/fonts/DepartureMono-Regular.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
body {
font-family: 'Departure Mono', monospace;
margin: 0;
padding: 0;
}
h1, h2, h3, h4, h5, h6, p, a, li, span, button, input, label {
font-family: 'Departure Mono', monospace;
}

View file

@ -1,16 +1,44 @@
<script>
import Peelable from '$lib/components/Peelable.svelte';
import Background from '$lib/components/Background.svelte';
import hackClubLogo from '$lib/assets/images/hackClub.png';
let logoTransform = $state('');
function handleLogoMouseMove(e) {
const rect = e.currentTarget.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width - 0.5;
const y = (e.clientY - rect.top) / rect.height - 0.5;
const rotateY = x * 20;
const rotateX = -y * 20;
logoTransform = `perspective(500px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
}
function handleLogoMouseLeave() {
logoTransform = '';
}
function handleLogin() {
window.location.href = '/login';
window.location.href = '/dash';
}
</script>
<Background />
<div class="container">
<h1>Stickers</h1>
<h1>
<img
class="title-logo"
src={hackClubLogo}
alt="Stickers!"
style:transform={logoTransform}
onmousemove={handleLogoMouseMove}
onmouseleave={handleLogoMouseLeave}
>
</h1>
<p>Manage everything sticky! Get free stickers for signing up, hack or trade to earn rare stickers and certify your collection.</p>
<p>Manage everything sticky! Get free stickers for signing up, hack or trade to earn rare stickers and certify your collection</p>
<Peelable
@ -31,11 +59,11 @@
{/snippet}
{#snippet bottomContent()}
<div class="sticker-surface">
<span></span>
<span style="color: black; font-size: 2xrem;">Loading...</span>
</div>
{/snippet}
</Peelable>
<p>*footer joke here</p>
<p>*with Hack Club</p>
</div>
<style>
@ -47,29 +75,44 @@
font-display: swap;
}
:global(html, body) {
overflow: hidden;
height: 100%;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
justify-content: flex-start;
height: 100vh;
text-align: center;
font-family: 'Departure Mono', monospace;
padding: 2rem;
background: #eeeeee;
padding: 0 2rem 2rem 2rem;
background: transparent;
overflow: hidden;
}
h1 {
font-size: 10rem;
margin-bottom: 1rem;
margin: -20px 0 1rem 0;
font-weight: 400;
}
.title-logo {
max-width: 100%;
height: auto;
transition: transform 0.15s ease-out;
transform-style: preserve-3d;
}
p {
font-size: 2rem;
max-width: 60vw;
margin: 0.5rem 0;
opacity: 0.8;
background: rgba(250, 248, 245, 0.9);
padding: 0.5rem 1rem;
border-radius: 0.25rem;
}
:global(.login-sticker) {
width: clamp(150px, 20vw, 650px);

View file

@ -0,0 +1,24 @@
<script>
import Background from '$lib/components/Background.svelte';
import Navbar from '$lib/components/Navbar.svelte';
import '$lib/styles/global.css';
let { children } = $props();
</script>
<svelte:head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</svelte:head>
<Background />
<Navbar active="dash" />
<div class="page-content">
{@render children()}
</div>
<style>
.page-content {
padding: 2rem;
}
</style>

View file

@ -0,0 +1,281 @@
<script>
import Peelable from '$lib/components/Peelable.svelte';
import stickersBg from '$lib/assets/images/stickers.jpg';
</script>
<div class="layout">
<div class="left-column">
<h1><mark>What's new</mark></h1>
<div class="cards">
<div class="card">
<p>USER is looking for a sticker that you own! Are you open to trade?</p>
<Peelable
class="btn-sticker"
corner="bottom-right"
peelOnHover={true}
hoverPeelAmount={0.3}
borderRadius="0.5rem"
>
{#snippet topContent()}
<div class="sticker-btn">Open</div>
{/snippet}
{#snippet backContent()}
<div class="sticker-back"></div>
{/snippet}
{#snippet bottomContent()}
<div class="sticker-surface"></div>
{/snippet}
</Peelable>
</div>
<div class="card">
<p>STICKER is X% cheaper this week</p>
<Peelable
class="btn-sticker"
corner="bottom-right"
peelOnHover={true}
hoverPeelAmount={0.3}
borderRadius="0.5rem"
>
{#snippet topContent()}
<div class="sticker-btn">Shop</div>
{/snippet}
{#snippet backContent()}
<div class="sticker-back"></div>
{/snippet}
{#snippet bottomContent()}
<div class="sticker-surface"></div>
{/snippet}
</Peelable>
</div>
<div class="card">
<p>New sticker drop! Vote on the best option now!</p>
<Peelable
class="btn-sticker"
corner="bottom-right"
peelOnHover={true}
hoverPeelAmount={0.3}
borderRadius="0.5rem"
>
{#snippet topContent()}
<div class="sticker-btn">Vote</div>
{/snippet}
{#snippet backContent()}
<div class="sticker-back"></div>
{/snippet}
{#snippet bottomContent()}
<div class="sticker-surface"></div>
{/snippet}
</Peelable>
</div>
</div>
</div>
<div class="divider"></div>
<div class="right-column">
<div class="right-header">
<h1><mark>Your collection</mark></h1>
<div class="button-group">
<button class="btn-left">Claim stickers</button>
<button class="btn-right">Place stickers</button>
</div>
</div>
<div class="canvas" style="background-image: url({stickersBg});">
<div class="empty-overlay">
<b><u>No stickers placed!</u></b>
</div>
</div>
</div>
</div>
<style>
.layout {
display: flex;
gap: 2rem;
height: calc(100vh - 120px);
overflow: hidden;
}
.left-column {
flex: 0 0 500px;
min-width: 500px;
overflow-y: auto;
padding-bottom: 2rem;
}
.cards {
display: flex;
flex-direction: column;
}
.divider {
width: 2px;
background: #333;
flex-shrink: 0;
margin-bottom: 2rem;
}
.right-column {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
padding-bottom: 2rem;
}
.canvas {
flex: 1;
background-color: rgba(255, 255, 255, 0.95);
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
border: 2px solid #333;
border-radius: 0.5rem;
overflow-y: auto;
overscroll-behavior: contain;
position: relative;
}
.empty-overlay {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 2rem;
text-align: center;
}
.empty-overlay mark {
background-color: #d9c9b6;
padding: 0.5rem 1rem;
}
.right-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
margin-bottom: 1rem;
flex-shrink: 0;
}
.right-header h1 {
margin: 0;
}
h1 {
font-size: 3rem;
margin: 0 0 2rem 0;
}
.card {
background: rgba(250, 248, 245, 0.95);
padding: 1.5rem;
border-radius: 0.5rem;
border: 2px solid #333;
margin-bottom: 1.5rem;
}
p {
font-size: 1.5rem;
margin: 0 0 1rem 0;
}
:global(.btn-sticker) {
width: 180px;
height: 50px;
cursor: pointer;
}
.sticker-btn {
width: 100%;
height: 100%;
background: #444444;
border-radius: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1rem;
}
.sticker-back {
width: 100%;
height: 100%;
background: #d9c9b6;
border-radius: 0.5rem;
}
.sticker-surface {
width: 100%;
height: 100%;
background: #d1a874;
border-radius: 0.5rem;
}
mark {
background-color: #d9c9b6;
padding: 0 0.2rem;
}
@media (max-width: 900px) {
.layout {
flex-direction: column;
height: auto;
overflow: visible;
}
.left-column {
flex: 0 0 auto;
min-width: 0;
max-width: 100%;
overflow-y: visible;
}
.right-column {
padding-bottom: 2rem;
}
.divider {
width: 100%;
height: 2px;
margin: 1rem 0;
}
.canvas {
min-height: 50vh;
height: auto;
}
}
.button-group {
display: flex;
}
.button-group button {
background: #444;
color: white;
border: 2px solid #333;
padding: 0.75rem 1.25rem;
font-size: 1rem;
cursor: pointer;
font-family: inherit;
}
.button-group button:hover {
background: #555;
}
.btn-left {
border-radius: 0.5rem 0 0 0.5rem;
border-right: 1px solid #333;
}
.btn-right {
border-radius: 0 0.5rem 0.5rem 0;
border-left: 1px solid #333;
}
</style>

View file

@ -0,0 +1,24 @@
<script>
import Background from '$lib/components/Background.svelte';
import Navbar from '$lib/components/Navbar.svelte';
import '$lib/styles/global.css';
let { children } = $props();
</script>
<svelte:head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</svelte:head>
<Background />
<Navbar active="leaderboard" />
<div class="page-content">
{@render children()}
</div>
<style>
.page-content {
padding: 2rem;
}
</style>

View file

View file

@ -0,0 +1,24 @@
<script>
import Background from '$lib/components/Background.svelte';
import Navbar from '$lib/components/Navbar.svelte';
import '$lib/styles/global.css';
let { children } = $props();
</script>
<svelte:head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</svelte:head>
<Background />
<Navbar active="leaderboard" />
<div class="page-content">
{@render children()}
</div>
<style>
.page-content {
padding: 2rem;
}
</style>

View file

View file

View file

@ -0,0 +1,24 @@
<script>
import Background from '$lib/components/Background.svelte';
import Navbar from '$lib/components/Navbar.svelte';
import '$lib/styles/global.css';
let { children } = $props();
</script>
<svelte:head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</svelte:head>
<Background />
<Navbar active="trade" />
<div class="page-content">
{@render children()}
</div>
<style>
.page-content {
padding: 2rem;
}
</style>

View file

View file

@ -0,0 +1,24 @@
<script>
import Background from '$lib/components/Background.svelte';
import Navbar from '$lib/components/Navbar.svelte';
import '$lib/styles/global.css';
let { children } = $props();
</script>
<svelte:head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</svelte:head>
<Background />
<Navbar active="vault" />
<div class="page-content">
{@render children()}
</div>
<style>
.page-content {
padding: 2rem;
}
</style>

View file