Skip to content

Commit 8ba81e8

Browse files
committed
published realse
1 parent 3ba69f9 commit 8ba81e8

25 files changed

Lines changed: 1010 additions & 217 deletions

.env.example

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

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ logs
2525

2626
# VSC
2727
.history
28+
im.md

app/app.vue

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,16 @@ useHead({
1818
})
1919
2020
useSeoMeta({
21-
titleTemplate: '%s - Nuxt SaaS template',
22-
ogImage: 'https://ui.nuxt.com/assets/templates/nuxt/saas-light.png',
23-
twitterImage: 'https://ui.nuxt.com/assets/templates/nuxt/saas-light.png',
24-
twitterCard: 'summary_large_image'
21+
titleTemplate: '%s - NLFTs Developer Program',
22+
title: 'NLFTs Developer Program Member',
23+
description: 'Bergabunglah dengan program eksklusif NLFTs Developer Member. Temukan modul, komponen, dan komunitas developer terbuka kami.',
24+
ogTitle: 'NLFTs Developer Program Member',
25+
ogDescription: 'Bergabunglah dengan program eksklusif NLFTs Developer Member. Temukan modul, komponen, dan komunitas developer terbuka kami.',
26+
ogImage: '/og-image.png', // Temporary, will be generated dynamically
27+
twitterImage: '/og-image.png',
28+
twitterCard: 'summary_large_image',
29+
twitterTitle: 'NLFTs Developer Program Member',
30+
twitterDescription: 'Bergabunglah dengan program eksklusif NLFTs Developer Member.'
2531
})
2632
2733
const { data: navigation } = await useAsyncData('navigation', () => queryCollectionNavigation('docs'), {

app/components/AppFooter.vue

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -102,32 +102,24 @@ function onSubmit() {
102102

103103
<template #left>
104104
<p class="text-muted text-sm">
105-
NLFTs alright reserved • Copyright © {{ new Date().getFullYear() }}
105+
NLFTs All Rights Reserved • Copyright © {{ new Date().getFullYear() }}
106106
</p>
107107
</template>
108108

109109
<template #right>
110110
<UButton
111-
to="https://go.nuxt.com/discord"
111+
to="https://discord.gg/nlfts"
112112
target="_blank"
113113
icon="i-simple-icons-discord"
114-
aria-label="Nuxt on Discord"
114+
aria-label="NLFTs on Discord"
115115
color="neutral"
116116
variant="ghost"
117117
/>
118118
<UButton
119-
to="https://go.nuxt.com/x"
120-
target="_blank"
121-
icon="i-simple-icons-x"
122-
aria-label="Nuxt on X"
123-
color="neutral"
124-
variant="ghost"
125-
/>
126-
<UButton
127-
to="https://github.com/nuxt-ui-templates/saas"
119+
to="https://github.com/nlfts"
128120
target="_blank"
129121
icon="i-simple-icons-github"
130-
aria-label="Nuxt UI on GitHub"
122+
aria-label="NLFTs on GitHub"
131123
color="neutral"
132124
variant="ghost"
133125
/>

app/components/AppHeader.vue

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
<script setup lang="ts">
22
const route = useRoute()
3+
const { user, loginWithPopup, logout } = useGithubAuth()
34
45
const items = computed(() => [
56
{
67
label: 'Product',
78
to: '/product'
89
},
9-
{
10-
label: 'Use Cases',
11-
children: [
12-
{ label: 'Professional', to: '/use-cases/professional', icon: 'i-lucide-users', description: 'Enterprise-grade solutions' },
13-
{ label: 'Frontend', to: '/use-cases/frontend', icon: 'i-lucide-code-2', description: 'Beautiful user interfaces' },
14-
{ label: 'Fullstack', to: '/use-cases/fullstack', icon: 'i-lucide-layers', description: 'Complete web applications' }
15-
]
16-
},
1710
{
1811
label: 'Pricing',
1912
to: '/pricing'
@@ -49,13 +42,26 @@ const items = computed(() => [
4942
/>
5043

5144
<template #right>
45+
<div v-if="user" class="flex items-center gap-4">
46+
<UDropdownMenu
47+
:items="[{ label: 'Logout', icon: 'i-lucide-log-out', onSelect: logout }]"
48+
>
49+
<UAvatar
50+
:src="user.user_metadata.avatar_url"
51+
:alt="user.user_metadata.full_name"
52+
size="sm"
53+
class="cursor-pointer border border-white/10"
54+
/>
55+
</UDropdownMenu>
56+
</div>
5257
<UButton
58+
v-else
5359
label="login"
5460
color="primary"
5561
size="md"
5662
class="rounded-full px-6 font-semibold"
5763
trailing-icon="i-lucide-user"
58-
to="/login"
64+
@click="loginWithPopup"
5965
/>
6066
</template>
6167

@@ -68,12 +74,29 @@ const items = computed(() => [
6874

6975
<USeparator class="my-6" />
7076

77+
<div v-if="user" class="flex items-center gap-4 mb-3">
78+
<UAvatar
79+
:src="user.user_metadata.avatar_url"
80+
size="md"
81+
/>
82+
<div class="flex-1">
83+
<p class="text-sm font-medium">{{ user.user_metadata.full_name }}</p>
84+
<p class="text-xs text-neutral-400">{{ user.email }}</p>
85+
</div>
86+
<UButton
87+
icon="i-lucide-log-out"
88+
color="neutral"
89+
variant="ghost"
90+
@click="logout"
91+
/>
92+
</div>
7193
<UButton
94+
v-else
7295
label="login"
7396
color="primary"
74-
to="/login"
7597
block
7698
class="mb-3"
99+
@click="loginWithPopup"
77100
/>
78101
</template>
79102
</UHeader>

app/composables/useGithubAuth.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
export const useGithubAuth = () => {
2+
const supabase = useSupabaseClient()
3+
const user = useSupabaseUser()
4+
const runtimeConfig = useRuntimeConfig()
5+
6+
const login = async () => {
7+
const { error } = await supabase.auth.signInWithOAuth({
8+
provider: 'github',
9+
options: {
10+
redirectTo: `${runtimeConfig.public.siteUrl}/auth/callback`,
11+
queryParams: {
12+
access_type: 'offline',
13+
prompt: 'consent'
14+
}
15+
}
16+
})
17+
18+
if (error) {
19+
console.error('Login error:', error.message)
20+
return { error }
21+
}
22+
}
23+
24+
const loginWithPopup = () => {
25+
const width = 600
26+
const height = 700
27+
const left = window.screenX + (window.outerWidth - width) / 2
28+
const top = window.screenY + (window.outerHeight - height) / 2
29+
30+
const popup = window.open(
31+
'/auth/login-popup',
32+
'GitHub Login',
33+
`width=${width},height=${height},left=${left},top=${top},scrollbars=yes,status=yes`
34+
)
35+
36+
return new Promise((resolve, reject) => {
37+
const interval = setInterval(() => {
38+
if (!popup || popup.closed) {
39+
clearInterval(interval)
40+
resolve(user.value)
41+
}
42+
}, 500)
43+
})
44+
}
45+
46+
const logout = async () => {
47+
const { error } = await supabase.auth.signOut()
48+
if (error) {
49+
console.error('Logout error:', error.message)
50+
}
51+
}
52+
53+
return {
54+
user,
55+
login,
56+
loginWithPopup,
57+
logout
58+
}
59+
}

app/pages/about.vue

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<template>
2+
<UMain class="py-24">
3+
<UContainer>
4+
<UPageHeader
5+
title="About NLFTs"
6+
description="Cerita di balik inovasi dan komunitas pengembang kami."
7+
class="text-center"
8+
/>
9+
<UPageBody>
10+
<UCard class="max-w-3xl mx-auto mt-12 backdrop-blur-xl bg-neutral-900/50 border-neutral-800">
11+
<div class="text-center py-12">
12+
<UIcon name="i-lucide-info" class="w-16 h-16 mx-auto mb-6 text-primary" />
13+
<h2 class="text-2xl font-bold mb-4">Siapa Kami</h2>
14+
<p class="text-neutral-400">NLFTs adalah komunitas dan platform inovasi untuk pengembangan masa depan. Profil lengkap perusahaan sedang disiapkan.</p>
15+
</div>
16+
</UCard>
17+
</UPageBody>
18+
</UContainer>
19+
</UMain>
20+
</template>

app/pages/analytics.vue

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<template>
2+
<UMain class="py-24">
3+
<UContainer>
4+
<UPageHeader
5+
title="Analytics"
6+
description="Pantau performa dan wawasan mendalam aplikasi Anda."
7+
class="text-center"
8+
/>
9+
<UPageBody>
10+
<UCard class="max-w-3xl mx-auto mt-12 backdrop-blur-xl bg-neutral-900/50 border-neutral-800">
11+
<div class="text-center py-12">
12+
<UIcon name="i-lucide-bar-chart-3" class="w-16 h-16 mx-auto mb-6 text-primary" />
13+
<h2 class="text-2xl font-bold mb-4">Dashboard Analytics</h2>
14+
<p class="text-neutral-400">Fitur analitik sedang dalam proses integrasi.</p>
15+
</div>
16+
</UCard>
17+
</UPageBody>
18+
</UContainer>
19+
</UMain>
20+
</template>

app/pages/auth/callback.vue

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<script setup lang="ts">
2+
definePageMeta({
3+
layout: false
4+
})
5+
6+
onMounted(() => {
7+
// Check if there's a session or error in the URL hash/query
8+
// Supabase will automatically handle the session, we just need to close the popup
9+
setTimeout(() => {
10+
window.close()
11+
}, 2000)
12+
})
13+
</script>
14+
15+
<template>
16+
<div class="flex items-center justify-center min-h-screen bg-black text-white">
17+
<div class="text-center">
18+
<UIcon name="i-lucide-check-circle-2" class="w-12 h-12 mb-4 text-primary mx-auto" />
19+
<p class="text-lg font-medium">Successfully connected!</p>
20+
<p class="text-sm text-neutral-400">Closing window...</p>
21+
</div>
22+
</div>
23+
</template>

app/pages/auth/login-popup.vue

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<script setup lang="ts">
2+
definePageMeta({
3+
layout: false
4+
})
5+
6+
const { login } = useGithubAuth()
7+
8+
onMounted(() => {
9+
login()
10+
})
11+
</script>
12+
13+
<template>
14+
<div class="flex items-center justify-center min-h-screen bg-black text-white">
15+
<div class="text-center">
16+
<UIcon name="i-simple-icons-github" class="w-12 h-12 mb-4 animate-pulse mx-auto" />
17+
<p class="text-lg font-medium">Redirecting to GitHub...</p>
18+
</div>
19+
</div>
20+
</template>

0 commit comments

Comments
 (0)