Skip to content

Commit bf922e7

Browse files
LeafdTKjane-does-codingtechpixel
authored
feat: add final platform (#11)
* fix: remove duplicated read more button * fix: move copyright text to the bottom * fix: change otp redirect to /projects * feat: add logout button * feat: add shake to locked buttons * fix: prevent duplicate project creation * feat: add back button to create project page * fix: update back button logic on onboarding * feat: complete onboard on first project creation * feat: add crow loader * fix: change project types cards * feat: add more project types * fix: add xss and sql injection protection * fix: center read more button on mobile * fix: change 40 hours to 50 hours minimum * feat: add 404 page * add 404 page * fix read more button z index * add no projects case to projects page * fix: change hackatime information text * fix: change auth endpoint * fix: prevent 404 page from handling api requests * fix: change hour count * fix: make onboard use referal code * fix: change hour count * feat: color cards based on project type * fix: switch wildcard card to button * feat: onboarding background * feat: juicer cards :p * fix: shake less * fix: copy information from airtable to user table * fix: add referral code system * fix: add debuging to start script * feat: copy referreral link to clipboard * fix: add users_airtable table * fix: prompt for birthday * fix: update refferal code count * fix: make bottombar pages not clickable --------- Co-authored-by: Jane <[email protected]> Co-authored-by: techpixel <[email protected]>
1 parent 3bea018 commit bf922e7

File tree

53 files changed

+1125
-750
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1125
-750
lines changed

.github/workflows/build-staging.yaml

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
11
name: Build and Push Docker Images
22

33
on:
4-
workflow_call:
5-
inputs:
6-
path:
7-
description: Path to service directory
8-
required: false
9-
type: string
10-
workflow_dispatch:
11-
inputs:
12-
path:
13-
description: Path to service directory
14-
required: false
15-
type: string
4+
push:
5+
branches:
6+
- staging
167

178
jobs:
189
prepare:
@@ -71,14 +62,15 @@ jobs:
7162
username: ${{ github.actor }}
7263
password: ${{ secrets.GITHUB_TOKEN }}
7364

74-
- name: Set tag prefix
75-
id: tag-prefix
65+
- name: Generate build ID
66+
id: prep
7667
run: |
77-
if [ "${{ github.ref_name }}" = "main" ]; then
78-
echo "prefix=prod-" >> $GITHUB_OUTPUT
79-
else
80-
echo "prefix=staging-" >> $GITHUB_OUTPUT
81-
fi
68+
branch=${GITHUB_REF##*/}
69+
sha=${GITHUB_SHA::8}
70+
ts=$(date +%s)
71+
build_id="${branch}-${sha}-${ts}"
72+
echo "build_id=${build_id}" >> $GITHUB_OUTPUT
73+
echo "timestamp=${ts}" >> $GITHUB_OUTPUT
8274
8375
- name: Build and push image
8476
uses: docker/build-push-action@v5
@@ -87,7 +79,7 @@ jobs:
8779
file: ./${{ matrix.service }}/Dockerfile
8880
tags: |
8981
ghcr.io/${{ github.repository }}/staging-${{ matrix.service }}:latest
90-
ghcr.io/${{ github.repository }}/staging-${{ matrix.service }}:${{ matrix.version }}
82+
ghcr.io/${{ github.repository }}/staging-${{ matrix.service }}:${{ steps.prep.outputs.build_id }}
9183
push: true
9284
cache-from: type=gha
9385
cache-to: type=gha,mode=max

.github/workflows/release-staging.yaml

Lines changed: 0 additions & 41 deletions
This file was deleted.

env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ GATEWAY_PORT=3000
44
# User Service Configuration
55
USER_SERVICE_PORT=3002
66
USER_SERVICE_NODE_ENV=development
7+
NODE_ENV=development
78
USER_SERVICE_AIRTABLE_API_KEY=your_airtable_api_key_here
89
CORS_ORIGIN=http://localhost:5173,http://localhost:3000
910
MAIL_SERVICE_URL=http://localhost:3003
1011

12+
# Security Configuration
13+
COOKIE_DOMAIN=localhost
14+
1115
# Database Configuration (PostgreSQL)
1216
DATABASE_URL=postgresql://username:password@localhost:5432/midnight_db
1317
MAIL_SERVICE_DATABASE_URL=postgresql://username:password@localhost:5432/midnight_db
@@ -56,6 +60,8 @@ DD_ENV=production
5660
DD_VERSION=1.0.0
5761

5862
# Production Settings (uncomment for production)
63+
# NODE_ENV=production
5964
# USER_SERVICE_NODE_ENV=production
6065
# CORS_ORIGIN=https://your-frontend-domain.com,https://your-api-domain.com
6166
# PUBLIC_API_URL=https://your-api-domain.com
67+
# COOKIE_DOMAIN=.your-domain.com

lark-ui/src/lib/BottomNavigation.svelte

Lines changed: 118 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,41 @@
11
<script lang="ts">
22
import { goto } from '$app/navigation';
3+
import { getReferralCode } from './auth';
34
4-
const { onboarding = true } = $props();
5+
const { onboarding = false } = $props();
56
6-
let activeTab = 'create';
7+
let activeTab = $state('create');
8+
let shakingTab = $state('');
9+
10+
let referralPopover = $state(false);
11+
12+
function handleLockedClick(tab: string) {
13+
shakingTab = tab;
14+
setTimeout(() => {
15+
shakingTab = '';
16+
}, 800);
17+
}
18+
19+
async function showReferralPopover() {
20+
const referralCode = await getReferralCode();
21+
22+
if (referralCode?.rafflePos) {
23+
const referralLink = `https://midnight.1mp.dev/?code=${referralCode.rafflePos}`;
24+
navigator.clipboard.writeText(referralLink);
25+
}
26+
27+
referralPopover = true;
28+
setTimeout(() => {
29+
referralPopover = false;
30+
}, 4000);
31+
}
732
833
function navigateTo(tab: string) {
34+
if (onboarding && (tab === 'explore' || tab === 'shop')) {
35+
handleLockedClick(tab);
36+
return;
37+
}
38+
939
activeTab = tab;
1040
switch(tab) {
1141
case 'create':
@@ -33,33 +63,41 @@
3363
Create
3464
</button>
3565
<button
36-
class="nav-item {onboarding ? 'disabled' : 'enabled'}"
66+
class="nav-item {true ? 'disabled' : 'enabled'}"
3767
class:active={activeTab === 'explore'}
38-
onclick={() => navigateTo('explore')}
68+
class:shake={shakingTab === 'explore'}
3969
role="tab"
4070
aria-selected={activeTab === 'explore'}
4171
>
4272
Explore
43-
{#if onboarding}
73+
<!-- {#if onboarding} -->
4474
<img class="lock" src="/icons/lock.svg" alt="Lock" />
45-
{/if}
75+
<!-- {/if} -->
4676
</button>
4777
<button
48-
class="nav-item {onboarding ? 'disabled' : 'enabled'}"
78+
class="nav-item {true ? 'disabled' : 'enabled'}"
4979
class:active={activeTab === 'shop'}
50-
onclick={() => navigateTo('shop')}
80+
class:shake={shakingTab === 'shop'}
5181
role="tab"
5282
aria-selected={activeTab === 'shop'}
5383
>
5484
Shop
55-
{#if onboarding}
85+
<!-- {#if onboarding} -->
5686
<img class="lock" src="/icons/lock.svg" alt="Lock" />
57-
{/if}
87+
<!-- {/if} -->
5888
</button>
5989
</div>
6090
<div class="tray">
6191
{#if !onboarding}
62-
<img src="/bell-icon.svg" alt="Notification" />
92+
<!-- <img src="/icons/bell.svg" alt="Notification" /> -->
93+
<button class="referral" onclick={showReferralPopover}>
94+
{#if referralPopover}
95+
<div class="referral-popover">
96+
<p>Referral link copied to clipboard</p>
97+
</div>
98+
{/if}
99+
<img src="/icons/link.svg" alt="Referral" />
100+
</button>
63101
{/if}
64102
</div>
65103
</div>
@@ -73,7 +111,7 @@
73111
background: #2D273F;
74112
height: 137px;
75113
padding: 0 120px;
76-
z-index: 100;
114+
z-index: 200;
77115
78116
display: flex;
79117
align-items: center;
@@ -109,7 +147,6 @@
109147
110148
.disabled {
111149
color: #7C7C7C;
112-
pointer-events: none;
113150
}
114151
115152
.nav-item.active {
@@ -133,6 +170,74 @@
133170
height: 30px;
134171
rotate: -10deg;
135172
}
173+
174+
.tray {
175+
display: flex;
176+
gap: 32px;
177+
}
178+
179+
.referral {
180+
position: relative;
181+
}
182+
183+
.referral img {
184+
width: 48px;
185+
height: 48px;
186+
}
187+
188+
.referral:hover img {
189+
opacity: 0.8;
190+
cursor: pointer;
191+
}
192+
193+
.referral-popover {
194+
position: absolute;
195+
bottom: 120%;
196+
left: 50%;
197+
translate: -50% 0;
198+
z-index: 200;
199+
padding: 1.5rem 2rem;
200+
background-image: url('/shapes/shape-popover-2.svg');
201+
background-size: contain;
202+
background-repeat: no-repeat;
203+
white-space: nowrap;
204+
205+
animation: fadeInOut 4s cubic-bezier(0.68, -0.55, 0.265, 1.55) forwards;
206+
transform-origin: center bottom;
207+
}
208+
209+
@keyframes fadeInOut {
210+
0% {
211+
scale: 0;
212+
opacity: 0;
213+
}
214+
15%, 80% {
215+
scale: 1;
216+
opacity: 1;
217+
}
218+
100% {
219+
scale: 0;
220+
opacity: 0;
221+
}
222+
}
223+
224+
.referral-popover p {
225+
font-size: 16px;
226+
color: black;
227+
margin: 0;
228+
margin-bottom: 24px;
229+
translate: -10px 1px;
230+
}
231+
232+
@keyframes shake {
233+
0%, 100% { transform: translateX(0); }
234+
33% { transform: translateX(-5px); }
235+
66% { transform: translateX(5px); }
236+
}
237+
238+
.nav-item.shake {
239+
animation: shake 400ms;
240+
}
136241
137242
@media (max-width: 768px) {
138243
.nav-item {

lark-ui/src/lib/auth.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,22 @@ export async function completeOnboarding() {
5555
});
5656
}
5757

58+
export async function logout() {
59+
return await fetch(`${apiUrl}/api/user/auth/logout`, {
60+
method: 'POST',
61+
headers: { 'Content-Type': 'application/json' },
62+
credentials: 'include',
63+
});
64+
}
65+
5866

5967
// projects
6068

6169
export type Project = {
6270
projectId: string;
6371
userId: string;
6472
projectTitle: string;
65-
projectType: 'personal_website' | 'platformer_game' | 'wildcard';
73+
projectType: 'personal_website' | 'platformer_game' | 'website' | 'game' | 'terminal_cli' | 'desktop_app' | 'mobile_app' | 'wildcard';
6674
description: string;
6775
createdAt: Date;
6876
updatedAt: Date;
@@ -195,4 +203,20 @@ export async function verifyHackatimeOtp(otp: string) {
195203
});
196204

197205
return response;
206+
}
207+
208+
// referral code
209+
export async function getReferralCode() {
210+
const response = await fetch(`${apiUrl}/api/user/auth/raffle-pos`, {
211+
method: 'GET',
212+
headers: { 'Content-Type': 'application/json' },
213+
credentials: 'include'
214+
});
215+
216+
if (response.ok) {
217+
const data = await response.json();
218+
return data;
219+
} else {
220+
return null;
221+
}
198222
}

lark-ui/src/lib/cards/BaseCard.svelte

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<script lang="ts">
22
let { children, color = '#081832', href = '#' } = $props();
3+
4+
let randRot = $state(Math.random() > 0.5 ? 1 : -1);
35
</script>
46

57
<a href={href}>
6-
<div class="base-card">
8+
<div class="base-card" style="--rand-rot: {randRot}deg">
79
<div class="card-background" style="background-color: {color}"></div>
810
<div class="card-border"></div>
911
<div class="card-content">
@@ -18,12 +20,13 @@
1820
width: 207px;
1921
height: 308px;
2022
21-
transition: all 0.1s ease-in;
23+
transition: all 250ms cubic-bezier(0.3, 0.7, 0.4, 1);
2224
}
2325
2426
.base-card:hover {
25-
translate: 0px -8px;
26-
transition: all 0.1s ease-out;
27+
scale: 1.035;
28+
rotate: var(--rand-rot);
29+
transition: all 250ms cubic-bezier(0.3, 0.7, 0.4, 1.5);
2730
cursor: pointer;
2831
}
2932

0 commit comments

Comments
 (0)