Skip to content

Commit

Permalink
Merge pull request #28 from BlueScript-NPO/auth
Browse files Browse the repository at this point in the history
BlueScript Account
  • Loading branch information
SuhJae authored Feb 4, 2025
2 parents f03e51b + 0f22213 commit 32720d9
Show file tree
Hide file tree
Showing 14 changed files with 629 additions and 85 deletions.
6 changes: 3 additions & 3 deletions app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ export default defineAppConfig({
primary:
"text-primary-500 hover:bg-primary-50 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-primary-500",
white:
"text-gray-900 hover:bg-white focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-primary-500",
gray: "text-gray-700 hover:bg-gray-100 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-500",
"text-gray-900 hover:bg-white focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-primary-500 hover:bg-gray-50",
gray: "text-gray-700 hover:bg-gray-100 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-500, hover:bg-gray-50",
black:
"text-gray-900 hover:bg-gray-900 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-primary-500",
"text-gray-900 hover:bg-gray-900 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-primary-500 hover:bg-gray-800",
},
link: {
primary:
Expand Down
48 changes: 43 additions & 5 deletions app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@
</template>

<script setup lang="ts">
import { ParsedContent } from "@nuxt/content";
const { t } = useI18n();
const colorMode = useColorMode();
const supabase = useSupabaseClient();
const localePath = useLocalePath();
const isDark = computed({
get() {
return colorMode.value === "dark";
Expand All @@ -33,14 +38,47 @@ const isDark = computed({
},
});
const route = useRoute();
const router = useRouter();
const { locale, availableLocales } = useI18n();
const lang = ref(route.query.lang as string);
const head = useLocaleHead({
addDirAttribute: true,
identifierAttribute: "id",
addSeoAttributes: true,
});
const signOut = async () => {
const { error } = await supabase.auth.signOut();
if (error) console.log(error);
navigateTo(localePath("/auth"));
};
const { data: navigation } = await useAsyncData("navigation", () =>
fetchContentNavigation()
);
const { data: files } = useLazyFetch<ParsedContent[]>("/api/search.json", {
default: () => [],
server: true,
});
const links = computed(() => [
{
label: t("nav.docs"),
to: localePath("/docs"),
icon: "i-ph-book",
},
{
label: t("nav.train"),
to: localePath("/train"),
icon: "i-ph-yin-yang",
},
{
label: t("nav.result"),
to: localePath("/result"),
icon: "i-ph-chart-bar",
},
]);
provide("signOut", signOut);
provide("navigation", navigation);
provide("files", files);
provide("links", links);
</script>
123 changes: 123 additions & 0 deletions components/AppHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<script setup lang="ts">
import LangSwitcher from "~/components/LangSwitcher.vue";
const { toggleContentSearch } = useUIState();
const { t } = useI18n();
const localePath = useLocalePath();
const user = useSupabaseUser();
const signOut = inject<() => void>("signOut");
const links = inject<{ label: string; icon: string; to?: string }[]>("links");
const items = [
[
{
slot: "account",
label: user?.value?.user_metadata.full_name,
disabled: true,
},
],
[
{
label: t("nav.account.dashboard"),
icon: "i-ph-speedometer",
to: localePath("/dashboard"),
},
],
[
{
label: t("nav.account.signOut"),
icon: "i-ph-arrow-line-up-right",
click: signOut,
color: "red",
},
],
];
</script>

<template>
<UHeader>
<template #left>
<NuxtLink :to="localePath('/')">
<Logo class="h-6 hover:opacity-90" />
</NuxtLink>
<UHeaderLinks :links="links" class="hidden sm:flex" />
</template>

<template #right>
<UContentSearchButton
class="hidden w-full lg:flex max-w-56 text-zinc-600 dark:text-zinc-300"
size="sm"
:label="t('search.placeholder')"
/>
<ClientOnly>
<UButton
:label="t('nav.account.signIn')"
color="black"
variant="ghost"
trailing-icon="i-ph-arrow-right"
class=""
:to="localePath('/auth')"
v-if="!user"
/>
<UDropdown
:items="items"
:popper="{ placement: 'bottom' }"
v-else
class="ml-2"
>
<UButton color="black" variant="ghost" class="flex items-center p-0">
<span class="hidden lg:block max-w-[10rem] truncate">
{{ user?.user_metadata.full_name }}
</span>
<UAvatar
:src="user?.user_metadata.avatar_url"
size="sm"
alt="User Avatar"
/>
</UButton>
<template #account="{ item }">
<div class="text-left">
<p>{{ t("nav.account.signedInAs") }}</p>
<p class="truncate font-medium text-gray-900 dark:text-white">
{{ item.label }}
</p>
</div>
</template>

<template #item="{ item }">
<span class="truncate">{{ item.label }}</span>

<UIcon
:name="item.icon"
class="flex-shrink-0 h-4 w-4 text-gray-400 dark:text-gray-500 ms-auto"
/>
</template>
</UDropdown>
</ClientOnly>
<UButton
class="lg:hidden"
variant="ghost"
color="white"
icon="i-ph-magnifying-glass"
aria-label="Search documentation"
@click="toggleContentSearch"
></UButton>
</template>

<template #panel>
<span class="sm:hidden">
<ClientOnly>
<UButtonGroup orientation="horizontal" class="w-full">
<UColorModeSelect class="w-full" />
<LangSwitcher class="w-full" />
</UButtonGroup>
</ClientOnly>
<UDivider class="my-3" />

<UNavigationLinks :links="links" />
<UDivider class="my-3" />
</span>
<DocsNav />
</template>
</UHeader>
</template>
29 changes: 29 additions & 0 deletions layouts/dashboard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script setup lang="ts">
const localePath = useLocalePath();
const { t } = useI18n();
const links = [
{
label: t("dashboard.nav.home"),
icon: "i-ph-house-line",
to: localePath("/dashboard"),
},
{
label: t("dashboard.nav.settings"),
icon: "i-ph-gear",
to: localePath("/dashboard/settings"),
},
];
</script>

<template>
<AppHeader />
<div class="w-full flex justify-center">
<div class="max-w-7xl w-full">
<UDashboardToolbar class="py-0 px-4 overflow-x-auto">
<UHorizontalNavigation :links="links" />
</UDashboardToolbar>
<slot />
</div>
</div>
</template>
81 changes: 6 additions & 75 deletions layouts/default.vue
Original file line number Diff line number Diff line change
@@ -1,84 +1,15 @@
<script setup lang="ts">
import type { ParsedContent } from "@nuxt/content";
import LangSwitcher from "~/components/LangSwitcher.vue";
const { toggleContentSearch } = useUIState();
const { t } = useI18n();
const localePath = useLocalePath();
import type { NavItem } from "@nuxt/content";
import AppHeader from "~/components/AppHeader.vue";
const { data: navigation } = await useAsyncData("navigation", () =>
fetchContentNavigation()
);
const { data: files } = useLazyFetch<ParsedContent[]>("/api/search.json", {
default: () => [],
server: true,
});
const links = computed(() => [
{
label: t("nav.docs"),
to: localePath("/docs"),
icon: "i-ph-book",
},
{
label: t("nav.train"),
to: localePath("/train"),
icon: "i-ph-yin-yang",
},
{
label: t("nav.result"),
to: localePath("/result"),
icon: "i-ph-chart-bar",
},
]);
provide("navigation", navigation);
provide("files", files);
const files = inject<ParsedContent[]>("files");
const links = inject<{ label: string; icon: string; to?: string }[]>("links");
const navigation = inject<NavItem[]>("navigation");
</script>

<template>
<UHeader>
<template #left>
<NuxtLink :to="localePath('/')">
<Logo class="h-6 hover:opacity-90" />
</NuxtLink>
<UHeaderLinks :links="links" class="hidden sm:flex" />
</template>

<template #right>
<UButton
class="block md:hidden"
variant="ghost"
color="gray"
square
icon="i-ph-magnifying-glass"
aria-label="Search documentation"
@click="toggleContentSearch"
></UButton>
<UContentSearchButton
class="hidden w-full md:flex md:max-w-48 lg:max-w-56 text-zinc-600 dark:text-zinc-300"
size="sm"
:label="t('search.placeholder')"
/>
</template>

<template #panel>
<span class="sm:hidden">
<ClientOnly>
<UButtonGroup orientation="horizontal" class="w-full">
<UColorModeSelect class="w-full" />
<LangSwitcher class="w-full" />
</UButtonGroup>
</ClientOnly>
<UDivider class="my-3" />

<UNavigationLinks :links="links" />
<UDivider class="my-3" />
</span>
<DocsNav />
</template>
</UHeader>

<AppHeader />
<UMain>
<slot />
</UMain>
Expand Down
56 changes: 55 additions & 1 deletion locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,14 @@
"home": "Home",
"train": "Training",
"result": "Result",
"docs": "Docs"
"docs": "Docs",
"dashboard": "Dashboard",
"account": {
"signIn": "Sign In",
"signedInAs": "Signed in as",
"dashboard": "Dashboard",
"signOut": "Sign Out"
}
},
"docs": {
"toc": "TOC"
Expand Down Expand Up @@ -189,5 +196,52 @@
"correctCount": "Correct Count",
"correctCountDesc": "Number of correct responses",
"upload": "Load Result"
},
"auth": {
"title": "Sign In",
"description": "Sign in to save your training results and settings.",
"OAuth": {
"google": "Continue with Google"
}
},
"dashboard": {
"nav": {
"home": "Home",
"settings": "Settings"
},
"home": {
"welcome": "Hello from BlueScript!",
"description": "BlueScript Account is under development. It will allow you to save your training results and settings. Stay tuned for updates!"
},
"settings": {
"updateSuccess": "Settings updated successfully.",
"updateError": "There was an error updating your settings. Please try again.",
"validate": {
"name": "Please enter your name.",
"email": "Email is invalid."
},
"theme": {
"title": "Theme",
"description": "Choose a theme that suits your preference."
},
"account": {
"title": "Account",
"description": "Update your account details.",
"save": "Save Changes"
},
"name": {
"title": "Name",
"description": "Update your username It will appear in profile, training results, and throughout the app."
},
"email": {
"title": "Email",
"description": "Email is managed by OAuth providers, and cannot be changed. It will be used for notifications."
},
"signOut": {
"title": "Sign Out",
"description": "Sign out of your account.",
"button": "Sign Out"
}
}
}
}
Loading

0 comments on commit 32720d9

Please sign in to comment.