mirror of
https://github.com/supabase/supabase.git
synced 2026-06-20 22:06:04 +08:00
* docs: add vue social auth * docs: add nuxt social auth * docs: nuxt social auth typo * docs: vue-nuxt-social-auth cr fix * Apply suggestion from @saltcod --------- Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> Co-authored-by: Terry Sutton <saltcod@gmail.com>
42 lines
12 KiB
JSON
42 lines
12 KiB
JSON
{
|
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
"name": "password-based-auth-vue",
|
|
"type": "registry:block",
|
|
"title": "Password Based Auth flow for Vue and Supabase",
|
|
"description": "Password Based Auth flow for Vue and Supabase",
|
|
"dependencies": [
|
|
"@supabase/supabase-js@latest"
|
|
],
|
|
"registryDependencies": [
|
|
"button",
|
|
"card",
|
|
"input",
|
|
"label"
|
|
],
|
|
"files": [
|
|
{
|
|
"path": "registry/default/password-based-auth/vue/components/login-form.vue",
|
|
"content": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { createClient } from \"@/lib/supabase/client\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Input } from \"@/components/ui/input\"\nimport { Label } from \"@/components/ui/label\"\n\nconst email = ref(\"\")\nconst error = ref<string | null>(null)\nconst success = ref(false)\nconst isLoading = ref(false)\n\nconst handleForgotPassword = async (e: Event) => {\n e.preventDefault()\n const supabase = createClient()\n isLoading.value = true\n error.value = null\n\n try {\n const { error: supabaseError } = await supabase.auth.resetPasswordForEmail(email.value, {\n redirectTo: \"http://localhost:3000/update-password\",\n })\n if (supabaseError) throw supabaseError\n success.value = true\n } catch (err: unknown) {\n error.value = err instanceof Error ? err.message : \"An error occurred\"\n } finally {\n isLoading.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-6\">\n <Card v-if=\"success\">\n <CardHeader>\n <CardTitle class=\"text-2xl\">Check Your Email</CardTitle>\n <CardDescription>Password reset instructions sent</CardDescription>\n </CardHeader>\n <CardContent>\n <p class=\"text-sm text-muted-foreground\">\n If you registered using your email and password, you will receive a password reset email.\n </p>\n </CardContent>\n </Card>\n\n <Card v-else>\n <CardHeader>\n <CardTitle class=\"text-2xl\">Reset Your Password</CardTitle>\n <CardDescription>\n Type in your email and we'll send you a link to reset your password\n </CardDescription>\n </CardHeader>\n <CardContent>\n <form @submit=\"handleForgotPassword\">\n <div class=\"flex flex-col gap-6\">\n <div class=\"grid gap-2\">\n <Label for=\"email\">Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"m@example.com\"\n required\n v-model=\"email\"\n />\n </div>\n <p v-if=\"error\" class=\"text-sm text-red-500\">{{ error }}</p>\n <Button type=\"submit\" class=\"w-full\" :disabled=\"isLoading\">\n {{ isLoading ? \"Sending...\" : \"Send reset email\" }}\n </Button>\n </div>\n <div class=\"mt-4 text-center text-sm\">\n Already have an account?\n <a href=\"/login\" class=\"underline underline-offset-4\">Login</a>\n </div>\n </form>\n </CardContent>\n </Card>\n </div>\n</template>\n",
|
|
"type": "registry:component",
|
|
"target": "components/login-form.vue"
|
|
},
|
|
{
|
|
"path": "registry/default/password-based-auth/vue/components/sign-up-form.vue",
|
|
"content": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { createClient } from \"@/lib/supabase/client\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Input } from \"@/components/ui/input\"\nimport { Label } from \"@/components/ui/label\"\n\nconst email = ref(\"\")\nconst password = ref(\"\")\nconst repeatPassword = ref(\"\")\nconst error = ref<string | null>(null)\nconst isLoading = ref(false)\nconst success = ref(false)\n\nconst handleSignUp = async () => {\n const supabase = createClient()\n error.value = null\n\n if (password.value !== repeatPassword.value) {\n error.value = \"Passwords do not match\"\n return\n }\n\n isLoading.value = true\n try {\n const { error: supabaseError } = await supabase.auth.signUp({\n email: email.value,\n password: password.value,\n })\n if (supabaseError) throw supabaseError\n success.value = true\n } catch (err: unknown) {\n error.value = err instanceof Error ? err.message : \"An error occurred\"\n } finally {\n isLoading.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-6\">\n <Card v-if=\"success\">\n <CardHeader>\n <CardTitle class=\"text-2xl\">Thank you for signing up!</CardTitle>\n <CardDescription>Check your email to confirm</CardDescription>\n </CardHeader>\n <CardContent>\n <p class=\"text-sm text-muted-foreground\">\n You've successfully signed up. Please check your email to confirm your account before\n signing in.\n </p>\n </CardContent>\n </Card>\n\n <Card v-else>\n <CardHeader>\n <CardTitle class=\"text-2xl\">Sign up</CardTitle>\n <CardDescription>Create a new account</CardDescription>\n </CardHeader>\n <CardContent>\n <form @submit.prevent=\"handleSignUp\">\n <div class=\"flex flex-col gap-6\">\n <!-- Email -->\n <div class=\"grid gap-2\">\n <Label for=\"email\">Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"m@example.com\"\n required\n v-model=\"email\"\n />\n </div>\n\n <!-- Password -->\n <div class=\"grid gap-2\">\n <div class=\"flex items-center\">\n <Label for=\"password\">Password</Label>\n </div>\n <Input\n id=\"password\"\n type=\"password\"\n required\n v-model=\"password\"\n />\n </div>\n\n <!-- Repeat Password -->\n <div class=\"grid gap-2\">\n <div class=\"flex items-center\">\n <Label for=\"repeat-password\">Repeat Password</Label>\n </div>\n <Input\n id=\"repeat-password\"\n type=\"password\"\n required\n v-model=\"repeatPassword\"\n />\n </div>\n\n <!-- Error -->\n <p v-if=\"error\" class=\"text-sm text-red-500\">{{ error }}</p>\n\n <!-- Submit -->\n <Button type=\"submit\" class=\"w-full\" :disabled=\"isLoading\">\n {{ isLoading ? \"Creating an account...\" : \"Sign up\" }}\n </Button>\n </div>\n\n <div class=\"mt-4 text-center text-sm\">\n Already have an account?\n <a href=\"/login\" class=\"underline underline-offset-4\">Login</a>\n </div>\n </form>\n </CardContent>\n </Card>\n </div>\n</template>\n",
|
|
"type": "registry:component",
|
|
"target": "components/sign-up-form.vue"
|
|
},
|
|
{
|
|
"path": "registry/default/password-based-auth/vue/components/forgot-password-form.vue",
|
|
"content": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { createClient } from \"@/lib/supabase/client\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Input } from \"@/components/ui/input\"\nimport { Label } from \"@/components/ui/label\"\n\n\nconst email = ref(\"\")\nconst error = ref<string | null>(null)\nconst success = ref(false)\nconst isLoading = ref(false)\n\nconst handleForgotPassword = async (e: Event) => {\n e.preventDefault()\n const supabase = createClient()\n isLoading.value = true\n error.value = null\n\n try {\n const { error: supabaseError } = await supabase.auth.resetPasswordForEmail(email.value, {\n redirectTo: \"http://localhost:3000/update-password\",\n })\n if (supabaseError) throw supabaseError\n success.value = true\n } catch (err: unknown) {\n error.value = err instanceof Error ? err.message : \"An error occurred\"\n } finally {\n isLoading.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-6\">\n <Card v-if=\"success\">\n <CardHeader>\n <CardTitle class=\"text-2xl\">Check Your Email</CardTitle>\n <CardDescription>Password reset instructions sent</CardDescription>\n </CardHeader>\n <CardContent>\n <p class=\"text-sm text-muted-foreground\">\n If you registered using your email and password, you will receive a password reset email.\n </p>\n </CardContent>\n </Card>\n\n <Card v-else>\n <CardHeader>\n <CardTitle class=\"text-2xl\">Reset Your Password</CardTitle>\n <CardDescription>\n Type in your email and we'll send you a link to reset your password\n </CardDescription>\n </CardHeader>\n <CardContent>\n <form @submit=\"handleForgotPassword\">\n <div class=\"flex flex-col gap-6\">\n <div class=\"grid gap-2\">\n <Label for=\"email\">Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"m@example.com\"\n required\n v-model=\"email\"\n />\n </div>\n <p v-if=\"error\" class=\"text-sm text-red-500\">{{ error }}</p>\n <Button type=\"submit\" class=\"w-full\" :disabled=\"isLoading\">\n {{ isLoading ? \"Sending...\" : \"Send reset email\" }}\n </Button>\n </div>\n <div class=\"mt-4 text-center text-sm\">\n Already have an account?\n <a href=\"/login\" class=\"underline underline-offset-4\">Login</a>\n </div>\n </form>\n </CardContent>\n </Card>\n </div>\n</template>\n",
|
|
"type": "registry:component",
|
|
"target": "components/forgot-password-form.vue"
|
|
},
|
|
{
|
|
"path": "registry/default/password-based-auth/vue/components/update-password-form.vue",
|
|
"content": "<script setup lang=\"ts\">\nimport { ref } from \"vue\"\nimport { createClient } from \"@/lib/supabase/client\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"@/components/ui/card\"\nimport { Input } from \"@/components/ui/input\"\nimport { Label } from \"@/components/ui/label\"\n\nconst password = ref(\"\")\nconst error = ref<string | null>(null)\nconst isLoading = ref(false)\n\nconst handleUpdatePassword = async () => {\n const supabase = createClient()\n isLoading.value = true\n error.value = null\n\n try {\n const { error: supabaseError } = await supabase.auth.updateUser({\n password: password.value,\n })\n if (supabaseError) throw supabaseError\n // Redirect user after successful password update\n location.href = \"/protected\"\n } catch (err: unknown) {\n error.value = err instanceof Error ? err.message : \"An error occurred\"\n } finally {\n isLoading.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-6\">\n <Card>\n <CardHeader>\n <CardTitle class=\"text-2xl\">Reset Your Password</CardTitle>\n <CardDescription>Please enter your new password below.</CardDescription>\n </CardHeader>\n <CardContent>\n <form @submit.prevent=\"handleUpdatePassword\">\n <div class=\"flex flex-col gap-6\">\n <div class=\"grid gap-2\">\n <Label for=\"password\">New password</Label>\n <Input\n id=\"password\"\n type=\"password\"\n placeholder=\"New password\"\n required\n v-model=\"password\"\n />\n </div>\n <p v-if=\"error\" class=\"text-sm text-red-500\">{{ error }}</p>\n <Button type=\"submit\" class=\"w-full\" :disabled=\"isLoading\">\n {{ isLoading ? \"Saving...\" : \"Save new password\" }}\n </Button>\n </div>\n </form>\n </CardContent>\n </Card>\n </div>\n</template>\n",
|
|
"type": "registry:component",
|
|
"target": "components/update-password-form.vue"
|
|
}
|
|
]
|
|
} |