working auth
parent
079aed3ca4
commit
db4e4fb176
@ -0,0 +1,31 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
html {
|
||||
@apply bg-primary text-white;
|
||||
}
|
||||
|
||||
#__nuxt {
|
||||
@apply h-screen w-screen;
|
||||
}
|
||||
|
||||
.app {
|
||||
@apply flex w-full flex-col items-center px-12;
|
||||
}
|
||||
.content {
|
||||
@apply mx-12 flex h-full w-full max-w-3xl flex-row justify-center gap-5;
|
||||
}
|
||||
|
||||
|
||||
.sidebar {
|
||||
@apply sticky top-3 h-fit w-64 rounded-lg px-10 py-5 text-white;
|
||||
}
|
||||
|
||||
.main {
|
||||
@apply h-screen w-2/5;
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply bg-secondary;
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<div
|
||||
class="bg-secondary mx-auto mt-12 flex h-96 w-96 flex-col items-center justify-center gap-8 rounded-xl p-8">
|
||||
<div class="flex w-full flex-col gap-2">
|
||||
<label> Email </label>
|
||||
<input
|
||||
type="text"
|
||||
v-model="credential.email"
|
||||
placeholder="username" />
|
||||
</div>
|
||||
<div class="flex w-full flex-col gap-2">
|
||||
<label> Password </label>
|
||||
<input
|
||||
type="password"
|
||||
v-model="credential.password"
|
||||
placeholder="password" />
|
||||
</div>
|
||||
<p
|
||||
v-if="mode === 'login'"
|
||||
class="cursor-pointer text-blue-500 underline">
|
||||
Don't have an account? Sign up
|
||||
</p>
|
||||
<p
|
||||
v-if="mode === 'signup'"
|
||||
class="cursor-pointer text-blue-500 underline">
|
||||
Already have an account? Login
|
||||
</p>
|
||||
<button
|
||||
v-on="
|
||||
mode === 'login'
|
||||
? { click: () => signIn($event) }
|
||||
: { click: () => signUp($event) }
|
||||
">
|
||||
{{ mode === 'login' ? 'Login' : 'Sign Up' }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
mode: 'login' | 'signup';
|
||||
}
|
||||
|
||||
interface Credential {
|
||||
email: string;
|
||||
password: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
const credential: Credential = reactive({
|
||||
email: '',
|
||||
password: '',
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
mode: 'login',
|
||||
});
|
||||
|
||||
const supabase = useSupabaseAuthClient();
|
||||
|
||||
const signUp = async (event: Event) => {
|
||||
const { data: user, error } = await supabase.auth.signUp({
|
||||
email: credential.email,
|
||||
password: credential.password,
|
||||
});
|
||||
console.log('user', user);
|
||||
console.log('error', error);
|
||||
};
|
||||
|
||||
const signIn = async (event: Event) => {
|
||||
const { data: user, error } = await supabase.auth.signInWithPassword({
|
||||
email: credential.email,
|
||||
password: credential.password,
|
||||
});
|
||||
console.log('user', user);
|
||||
console.log('error', error);
|
||||
};
|
||||
</script>
|
||||
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<!-- card class css located at /assets/css/tailwind.css -->
|
||||
</template>
|
||||
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<div class="header">
|
||||
<img
|
||||
class="avatar"
|
||||
:src="avatar"
|
||||
alt="" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
avatar?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
avatar: 'https://www.redditstatic.com/avatars/avatar_default_02_FF4500.png',
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.header {
|
||||
@apply bg-secondary my-3 flex h-16 w-full max-w-3xl flex-row items-center justify-center rounded-lg;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@apply bg-secondary h-12 w-12 rounded-full;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,9 @@
|
||||
export default defineNuxtRouteMiddleware((to, from) => {
|
||||
const user = useSupabaseUser();
|
||||
|
||||
if (!user.value && to.path === '/notes') {
|
||||
return navigateTo('/login');
|
||||
} else if (user.value && to.path === '/login') {
|
||||
return navigateTo('/notes');
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<p> {{ $route.params.slug }} </p>
|
||||
</template>
|
||||
@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<div class="app">
|
||||
<Header />
|
||||
{{ user?.email }}
|
||||
<NuxtLink to="/notes"> Notes </NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: ['auth'],
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const user = useSupabaseUser();
|
||||
|
||||
watch(
|
||||
() => user.value,
|
||||
() => {
|
||||
if (user.value) {
|
||||
router.push('/notes');
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<div class="app">
|
||||
<Header />
|
||||
<div
|
||||
class="bg-secondary mx-auto mt-12 flex h-96 w-96 flex-col items-center justify-center gap-8 rounded-xl p-8">
|
||||
<div class="flex w-full flex-col gap-2">
|
||||
<label> Email </label>
|
||||
<input
|
||||
type="text"
|
||||
v-model="credential.email"
|
||||
placeholder="username" />
|
||||
</div>
|
||||
<div class="flex w-full flex-col gap-2">
|
||||
<label> Password </label>
|
||||
<input
|
||||
type="password"
|
||||
v-model="credential.password"
|
||||
placeholder="password" />
|
||||
</div>
|
||||
<p
|
||||
class="cursor-pointer text-blue-500 underline"
|
||||
@click="
|
||||
mode === 'login' ? (mode = 'signup') : (mode = 'login')
|
||||
">
|
||||
{{
|
||||
mode === 'login'
|
||||
? "Don't have an account? Sign up"
|
||||
: 'Already have an account? Login'
|
||||
}}
|
||||
</p>
|
||||
<button
|
||||
v-on="
|
||||
mode === 'login'
|
||||
? { click: () => signIn($event) }
|
||||
: { click: () => signUp($event) }
|
||||
">
|
||||
{{ mode === 'login' ? 'Login' : 'Sign Up' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: ['auth'],
|
||||
});
|
||||
|
||||
interface Credential {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
type Mode = 'login' | 'signup';
|
||||
|
||||
const credential: Credential = reactive({
|
||||
email: '',
|
||||
password: '',
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const supabase = useSupabaseAuthClient();
|
||||
const user = useSupabaseUser();
|
||||
const mode = ref<Mode>('login');
|
||||
|
||||
watch(
|
||||
() => user.value,
|
||||
() => {
|
||||
if (user.value) {
|
||||
router.push('/notes');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const signUp = async (event: Event) => {
|
||||
const { data: user, error } = await supabase.auth.signUp({
|
||||
email: credential.email,
|
||||
password: credential.password,
|
||||
});
|
||||
console.log('user', user);
|
||||
console.log('error', error);
|
||||
};
|
||||
|
||||
const signIn = async (event: Event) => {
|
||||
const { data: user, error } = await supabase.auth.signInWithPassword({
|
||||
email: credential.email,
|
||||
password: credential.password,
|
||||
});
|
||||
console.log('user', user);
|
||||
console.log('error', error);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
input {
|
||||
@apply h-12 w-full rounded-md border border-[#373737] bg-[#2b2b2b] p-4 text-lg placeholder:text-[#4f4f4f] focus:outline-none active:outline-none;
|
||||
}
|
||||
|
||||
button {
|
||||
@apply w-fit rounded-lg bg-blue-500 py-4 px-8;
|
||||
}
|
||||
|
||||
label {
|
||||
@apply w-full text-[#b3b3b3];
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<div class="app">
|
||||
<Header />
|
||||
|
||||
<div class="content">
|
||||
<div v-for="note in data?.notes">
|
||||
<LazyCardNote />
|
||||
</div>
|
||||
</div>
|
||||
{{ data }}
|
||||
|
||||
<button @click="signout">Sign Out</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: ['auth'],
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const supabase = useSupabaseAuthClient();
|
||||
const user = useSupabaseUser();
|
||||
|
||||
interface FetchOption {
|
||||
key?: string;
|
||||
headers: Record<'cookie', string | undefined>;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
console.log(user.value);
|
||||
});
|
||||
|
||||
const fetchOption: FetchOption = {
|
||||
key: user.value?.id,
|
||||
headers: useRequestHeaders(['cookie']),
|
||||
};
|
||||
|
||||
const { data: data } = await useFetch('/api/notes', fetchOption);
|
||||
|
||||
const signout = async () => {
|
||||
const { error } = await supabase.auth.signOut();
|
||||
router.push('/');
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -0,0 +1,15 @@
|
||||
import { serverSupabaseUser, serverSupabaseClient } from '#supabase/server';
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const user = await serverSupabaseUser(event);
|
||||
const supabase = serverSupabaseClient(event);
|
||||
|
||||
const { data: notes, error } = await supabase.from('notes').select('*');
|
||||
|
||||
if (!user) {
|
||||
throw createError({ statusCode: 401, message: 'Unauthorized' });
|
||||
}
|
||||
return { notes: notes };
|
||||
});
|
||||
Loading…
Reference in New Issue