✨ Sign up
This commit is contained in:
		| @@ -9,7 +9,9 @@ | ||||
|         </v-alert> | ||||
|       </v-expand-transition> | ||||
|  | ||||
|       <div class="flex justify-end"> | ||||
|       <div class="flex justify-between"> | ||||
|         <v-btn type="button" variant="plain" color="grey-darken-3" :to="{ name: 'auth.sign-up' }">Sign up</v-btn> | ||||
|  | ||||
|         <v-btn | ||||
|           type="submit" | ||||
|           variant="text" | ||||
|   | ||||
							
								
								
									
										16
									
								
								pkg/views/src/components/auth/CallbackNotify.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								pkg/views/src/components/auth/CallbackNotify.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| <template> | ||||
|   <div class="w-full max-w-[720px]"> | ||||
|     <v-expand-transition> | ||||
|       <v-alert v-show="route.query['redirect_uri']" variant="tonal" type="info" class="text-xs"> | ||||
|         You need to sign in before access that page. After you signed in, we will redirect you to: <br /> | ||||
|         <span class="font-mono">{{ route.query["redirect_uri"] }}</span> | ||||
|       </v-alert> | ||||
|     </v-expand-transition> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { useRoute } from "vue-router" | ||||
|  | ||||
| const route = useRoute() | ||||
| </script> | ||||
| @@ -15,8 +15,8 @@ | ||||
|         </template> | ||||
|  | ||||
|         <v-list density="compact"> | ||||
|           <v-list-item title="Sign in" prepend-icon="mdi-login-variant" /> | ||||
|           <v-list-item title="Create account" prepend-icon="mdi-account-plus" /> | ||||
|           <v-list-item title="Sign in" prepend-icon="mdi-login-variant" :to="{ name: 'auth.sign-in' }" /> | ||||
|           <v-list-item title="Create account" prepend-icon="mdi-account-plus" :to="{ name: 'auth.sign-up' }" /> | ||||
|         </v-list> | ||||
|       </v-menu> | ||||
|     </div> | ||||
|   | ||||
| @@ -15,7 +15,7 @@ const router = createRouter({ | ||||
|       path: "/auth", | ||||
|       children: [ | ||||
|         { path: "sign-in", name: "auth.sign-in", component: () => import("@/views/auth/sign-in.vue") }, | ||||
|         // { path: "sign-up", name: "auth.sign-up", component: () => import("@/views/auth/sign-up.vue") }, | ||||
|         { path: "sign-up", name: "auth.sign-up", component: () => import("@/views/auth/sign-up.vue") }, | ||||
|       ] | ||||
|     } | ||||
|   ], | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| <template> | ||||
|   <v-container class="h-screen flex flex-col gap-3 items-center justify-center"> | ||||
|     <callback-notify /> | ||||
|  | ||||
|     <v-card class="w-full max-w-[720px]" :loading="loading"> | ||||
|       <v-card-text class="card-grid pa-9"> | ||||
|         <div> | ||||
| @@ -30,6 +32,7 @@ | ||||
| <script setup lang="ts"> | ||||
| import { ref, type Component } from "vue" | ||||
| import Copyright from "@/components/Copyright.vue" | ||||
| import CallbackNotify from "@/components/auth/CallbackNotify.vue" | ||||
| import AccountLocator from "@/components/auth/AccountLocator.vue" | ||||
| import FactorPicker from "@/components/auth/FactorPicker.vue" | ||||
| import FactorApplicator from "@/components/auth/FactorApplicator.vue" | ||||
| @@ -66,4 +69,3 @@ const panels: { [id: string]: Component } = { | ||||
|   border-radius: 8px; | ||||
| } | ||||
| </style> | ||||
| @/components/Copyright.vue | ||||
|   | ||||
							
								
								
									
										162
									
								
								pkg/views/src/views/auth/sign-up.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								pkg/views/src/views/auth/sign-up.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| <template> | ||||
|   <v-container class="h-screen flex flex-col gap-3 items-center justify-center"> | ||||
|     <callback-notify /> | ||||
|  | ||||
|     <v-card class="w-full max-w-[720px]" :loading="loading"> | ||||
|       <v-card-text class="card-grid pa-9"> | ||||
|         <div> | ||||
|           <v-avatar color="accent" icon="mdi-login-variant" size="large" class="card-rounded mb-2" /> | ||||
|           <h1 class="text-2xl">Create an account</h1> | ||||
|           <p>Create an account on Solar Network. Then enjoy all our services.</p> | ||||
|         </div> | ||||
|  | ||||
|         <div class="flex items-center"> | ||||
|           <v-form class="flex-grow-1" @submit.prevent="submit"> | ||||
|             <v-row dense class="mb-3"> | ||||
|               <v-col :cols="6"> | ||||
|                 <v-text-field | ||||
|                   hide-details | ||||
|                   label="Name" | ||||
|                   autocomplete="username" | ||||
|                   variant="solo" | ||||
|                   density="comfortable" | ||||
|                   v-model="data.name" | ||||
|                 /> | ||||
|               </v-col> | ||||
|               <v-col :cols="6"> | ||||
|                 <v-text-field | ||||
|                   hide-details | ||||
|                   label="Nick" | ||||
|                   autocomplete="nickname" | ||||
|                   variant="solo" | ||||
|                   density="comfortable" | ||||
|                   v-model="data.nick" | ||||
|                 /> | ||||
|               </v-col> | ||||
|               <v-col :cols="12"> | ||||
|                 <v-text-field | ||||
|                   hide-details | ||||
|                   label="Email Address" | ||||
|                   type="email" | ||||
|                   variant="solo" | ||||
|                   density="comfortable" | ||||
|                   v-model="data.email" | ||||
|                 /> | ||||
|               </v-col> | ||||
|               <v-col :cols="12"> | ||||
|                 <v-text-field | ||||
|                   hide-details | ||||
|                   label="Password" | ||||
|                   type="password" | ||||
|                   autocomplete="new-password" | ||||
|                   variant="solo" | ||||
|                   density="comfortable" | ||||
|                   v-model="data.password" | ||||
|                 /> | ||||
|               </v-col> | ||||
|             </v-row> | ||||
|  | ||||
|             <v-expand-transition> | ||||
|               <v-alert v-show="error" variant="tonal" type="error" class="text-xs mb-3"> | ||||
|                 Something went wrong... {{ error }} | ||||
|               </v-alert> | ||||
|             </v-expand-transition> | ||||
|  | ||||
|             <div class="flex justify-between"> | ||||
|               <v-btn type="button" variant="plain" color="grey-darken-3" :to="{ name: 'auth.sign-in' }"> | ||||
|                 Sign in | ||||
|               </v-btn> | ||||
|  | ||||
|               <v-btn type="submit" variant="text" color="primary" append-icon="mdi-arrow-right" :disabled="loading"> | ||||
|                 Next | ||||
|               </v-btn> | ||||
|             </div> | ||||
|           </v-form> | ||||
|         </div> | ||||
|       </v-card-text> | ||||
|     </v-card> | ||||
|  | ||||
|     <v-dialog v-model="done" class="max-w-[560px]"> | ||||
|       <v-card title="Congratulations"> | ||||
|         <template #text> | ||||
|           You successfully created an account on Solar Network. Now sign in to your account and start exploring! | ||||
|         </template> | ||||
|         <template #actions> | ||||
|           <div class="flex flex-grow-1 justify-end"> | ||||
|             <v-btn @click="callback">Let's go</v-btn> | ||||
|           </div> | ||||
|         </template> | ||||
|       </v-card> | ||||
|     </v-dialog> | ||||
|  | ||||
|     <copyright /> | ||||
|   </v-container> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { ref } from "vue" | ||||
| import { request } from "@/scripts/request" | ||||
| import { useRoute, useRouter } from "vue-router" | ||||
| import Copyright from "@/components/Copyright.vue" | ||||
| import CallbackNotify from "@/components/auth/CallbackNotify.vue" | ||||
|  | ||||
| const error = ref<string | null>(null) | ||||
|  | ||||
| const route = useRoute() | ||||
| const router = useRouter() | ||||
|  | ||||
| const done = ref(false) | ||||
| const loading = ref(false) | ||||
|  | ||||
| const data = ref({ | ||||
|   name: "", | ||||
|   nick: "", | ||||
|   email: "", | ||||
|   password: "", | ||||
| }) | ||||
|  | ||||
| async function submit() { | ||||
|   const payload = data.value | ||||
|   if (!payload.name || !payload.nick || !payload.email || !payload.password) return | ||||
|  | ||||
|   loading.value = true | ||||
|   const res = await request("/api/users", { | ||||
|     method: "POST", | ||||
|     headers: { "Content-Type": "application/json" }, | ||||
|     body: JSON.stringify(data), | ||||
|   }) | ||||
|   if (res.status !== 200) { | ||||
|     error.value = await res.text() | ||||
|   } else { | ||||
|     done.value = true | ||||
|     error.value = null | ||||
|   } | ||||
|   loading.value = false | ||||
| } | ||||
|  | ||||
| function callback() { | ||||
|   if (route.params["closable"]) { | ||||
|     window.close() | ||||
|   } else { | ||||
|     router.push({ name: "auth.sign-in" }) | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped> | ||||
| .card-grid { | ||||
|   display: grid; | ||||
|   grid-template-columns: 1fr 1fr; | ||||
|   gap: 1rem; | ||||
| } | ||||
|  | ||||
| @media (max-width: 768px) { | ||||
|   .card-grid { | ||||
|     grid-template-columns: 1fr; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .card-rounded { | ||||
|   border-radius: 8px; | ||||
| } | ||||
| </style> | ||||
		Reference in New Issue
	
	Block a user