This commit is contained in:
2025-05-24 01:49:48 +09:00
commit 62abbcf4eb
2376 changed files with 325522 additions and 0 deletions

0
src/pages/auth/index.vue Normal file
View File

149
src/pages/auth/login-2.vue Normal file
View File

@@ -0,0 +1,149 @@
<script setup lang="ts">
const isLoading = ref(false)
const router = useRouter()
const route = useRoute()
const notyf = useNotyf()
const token = useUserToken()
const redirect = route.query.redirect as string
const handleLogin = async () => {
if (!isLoading.value) {
isLoading.value = true
await sleep(2000)
token.value = 'logged-in'
notyf.dismissAll()
notyf.primary('Welcome back, Erik Kovalsky')
if (redirect) {
router.push(redirect)
}
else {
router.push('/sidebar/dashboards')
}
isLoading.value = false
}
}
useHead({
title: 'Auth Login 2 - Vuero',
})
</script>
<template>
<div class="auth-wrapper-inner columns is-gapless">
<!-- Image section (hidden on mobile) -->
<div class="column login-column is-8 h-hidden-mobile h-hidden-tablet-p hero-banner">
<div class="hero login-hero is-fullheight is-app-grey">
<div class="hero-body is-justify-content-center is-fullwidth">
<div class="is-flex is-justify-content-center is-fullwidth">
<img
class="light-image has-light-shadow has-light-border"
src="/images/illustrations/apps/vuero-banking-light.webp"
alt=""
>
<img
class="dark-image has-light-shadow"
src="/images/illustrations/apps/vuero-banking-dark.webp"
alt=""
>
</div>
</div>
</div>
</div>
<!-- Form section -->
<div class="column is-4">
<div class="hero is-fullheight is-white">
<div class="hero-heading">
<div class="auth-logo">
<RouterLink to="/">
<AnimatedLogo
width="36px"
height="36px"
/>
</RouterLink>
<VDarkmodeToggle />
</div>
</div>
<div class="hero-body">
<div class="container">
<div class="columns">
<div class="column is-12">
<div class="auth-content">
<h2>Welcome Back.</h2>
<p>Please sign in to your account</p>
<RouterLink to="/auth/signup-2">
I do not have an account yet
</RouterLink>
</div>
<div class="auth-form-wrapper">
<!-- Login Form -->
<form
method="post"
novalidate
@submit.prevent="handleLogin"
>
<div class="login-form">
<!-- Username -->
<VField>
<VControl icon="lucide:user">
<VInput
type="text"
placeholder="Username"
autocomplete="username"
/>
</VControl>
</VField>
<!-- Password -->
<VField>
<VControl icon="lucide:lock">
<VInput
type="password"
placeholder="Password"
autocomplete="current-password"
/>
</VControl>
</VField>
<!-- Switch -->
<VField>
<VControl class="setting-item">
<VCheckbox
label="Remember me"
paddingless
/>
</VControl>
</VField>
<!-- Submit -->
<div class="login">
<VButton
:loading="isLoading"
color="primary"
type="submit"
bold
fullwidth
raised
>
Sign In
</VButton>
</div>
<div class="forgot-link has-text-centered">
<a>Forgot Password?</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>

130
src/pages/auth/login-3.vue Normal file
View File

@@ -0,0 +1,130 @@
<script setup lang="ts">
const isLoading = ref(false)
const router = useRouter()
const route = useRoute()
const notyf = useNotyf()
const token = useUserToken()
const redirect = route.query.redirect as string
const handleLogin = async () => {
if (!isLoading.value) {
isLoading.value = true
await sleep(2000)
token.value = 'logged-in'
notyf.dismissAll()
notyf.primary('Welcome back, Erik Kovalsky')
if (redirect) {
router.push(redirect)
}
else {
router.push('/sidebar/dashboards')
}
isLoading.value = false
}
}
useHead({
title: 'Auth Login 3 - Vuero',
})
</script>
<template>
<div class="auth-wrapper-inner is-single">
<LandingGrids class="is-contrasted" />
<!--Fake navigation-->
<div class="auth-nav">
<div class="left" />
<div class="center">
<RouterLink
to="/"
class="header-item"
>
<AnimatedLogo
width="38px"
height="38px"
/>
</RouterLink>
</div>
<div class="right">
<VDarkmodeToggle />
</div>
</div>
<!--Single Centered Form-->
<div class="single-form-wrap is-relative">
<div class="inner-wrap">
<!--Form Title-->
<div class="auth-head">
<h2>Welcome Back.</h2>
<p>Please sign in to your account</p>
<RouterLink to="/auth/signup-3">
I do not have an account yet
</RouterLink>
</div>
<!--Form-->
<div class="form-card">
<form
method="post"
novalidate
@submit.prevent="handleLogin"
>
<div class="login-form">
<VField>
<VControl icon="lucide:user">
<VInput
type="text"
placeholder="Username"
autocomplete="username"
/>
</VControl>
</VField>
<VField>
<VControl icon="lucide:lock">
<VInput
type="password"
placeholder="Password"
autocomplete="current-password"
/>
</VControl>
</VField>
<!-- Switch -->
<VField>
<VControl class="setting-item">
<VCheckbox
label="Remember me"
color="primary"
paddingless
/>
</VControl>
</VField>
<!-- Submit -->
<div class="login">
<VButton
:loading="isLoading"
type="submit"
color="primary"
bold
fullwidth
raised
>
Sign In
</VButton>
</div>
</div>
</form>
</div>
<div class="forgot-link has-text-centered">
<a>Forgot Password?</a>
</div>
</div>
</div>
</div>
</template>

759
src/pages/auth/login.vue Normal file
View File

@@ -0,0 +1,759 @@
<script setup lang="ts">
type StepId = 'login' | 'forgot-password'
const step = ref<StepId>('login')
const isLoading = ref(false)
const router = useRouter()
const route = useRoute()
const notyf = useNotyf()
const token = useUserToken()
const redirect = route.query.redirect as string
const handleLogin = async () => {
if (!isLoading.value) {
isLoading.value = true
await sleep(2000)
console.log('set token logged-in')
token.value = 'logged-in'
notyf.dismissAll()
notyf.primary('Welcome back, Erik Kovalsky')
if (redirect) {
router.push(redirect)
}
else {
router.push('/sidebar/dashboards')
}
isLoading.value = false
}
}
useHead({
title: 'Auth Login 1 - Vuero',
})
</script>
<template>
<div class="modern-login">
<div class="underlay h-hidden-mobile h-hidden-tablet-p" />
<div class="columns is-gapless is-vcentered">
<div class="column is-relative is-8 h-hidden-mobile h-hidden-tablet-p">
<div class="hero is-fullheight is-image">
<div class="hero-body">
<div class="container">
<div class="columns">
<div class="column">
<img
class="hero-image"
src="/images/illustrations/login/station.svg"
alt=""
>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="column is-4 is-relative">
<div class="top-tools">
<RouterLink
to="/"
class="top-logo"
>
<AnimatedLogo
width="38px"
height="38px"
/>
</RouterLink>
<VDarkmodeToggle />
</div>
<div class="is-form">
<div class="is-form-inner">
<div
class="form-text"
:class="[step !== 'login' && 'is-hidden']"
>
<h2>Sign In</h2>
<p>Welcome back to your account.</p>
</div>
<div
class="form-text"
:class="[step === 'login' && 'is-hidden']"
>
<h2>Recover Account</h2>
<p>Reset your account password.</p>
</div>
<form
method="post"
novalidate
:class="[step !== 'login' && 'is-hidden']"
class="login-wrapper"
@submit.prevent="handleLogin"
>
<VMessage color="primary">
<div>
<strong class="pr-1">email:</strong>
<span>john.doe@cssninja.io</span>
</div>
<div>
<strong class="pr-1">password:</strong>
<span>ada.lovelace</span>
</div>
</VMessage>
<VField>
<VControl icon="lnil lnil-envelope autv-icon">
<VLabel class="auth-label">
Email Address
</VLabel>
<VInput
type="email"
autocomplete="current-password"
/>
</VControl>
</VField>
<VField>
<VControl icon="lnil lnil-lock-alt autv-icon">
<VLabel class="auth-label">
Password
</VLabel>
<VInput
type="password"
autocomplete="current-password"
/>
</VControl>
</VField>
<VField>
<VControl class="is-flex">
<VLabel
raw
class="remember-toggle"
>
<VInput
raw
type="checkbox"
/>
<span class="toggler">
<span class="active">
<VIcon
icon="lucide:check"
/>
</span>
<span class="inactive">
<VIcon
icon="lucide:circle"
/>
</span>
</span>
</VLabel>
<VLabel
raw
class="remember-me"
>
Remember Me
</VLabel>
<a
tabindex="0"
role="button"
@keydown.enter.prevent="step = 'forgot-password'"
@click="step = 'forgot-password'"
>
Forgot Password?
</a>
</VControl>
</VField>
<div class="button-wrap has-help">
<VButton
id="login-button"
:loading="isLoading"
color="primary"
type="submit"
size="big"
rounded
raised
bold
>
Confirm
</VButton>
<span>
Or
<RouterLink to="/auth/signup-1">Create</RouterLink>
an account.
</span>
</div>
</form>
<form
method="post"
novalidate
:class="[step !== 'forgot-password' && 'is-hidden']"
class="login-wrapper"
@submit.prevent
>
<p class="recover-text">
Enter your email and click on the confirm button to reset your password.
We'll send you an email detailing the steps to complete the procedure.
</p>
<VField>
<VControl icon="lnil lnil-envelope autv-icon">
<VLabel class="auth-label">
Email Address
</VLabel>
<VInput
type="email"
autocomplete="current-password"
/>
</VControl>
</VField>
<div class="button-wrap">
<VButton
color="white"
size="big"
lower
rounded
@click="step = 'login'"
>
Cancel
</VButton>
<VButton
color="primary"
size="big"
type="submit"
lower
rounded
solid
@click="step = 'login'"
>
Confirm
</VButton>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.modern-login {
position: relative;
background: var(--white);
min-height: 100vh;
.column {
&.is-relative {
position: relative;
}
}
.hero {
&.has-background-image {
position: relative;
.hero-overlay {
position: absolute;
top: 0;
inset-inline-start: 0;
width: 100%;
height: 100%;
background: #5d4298 !important;
opacity: 0.6;
}
}
}
.underlay {
display: block;
position: absolute;
top: 0;
inset-inline-start: 0;
width: 66.6%;
height: 100%;
background: #fdfdfd;
z-index: 0;
}
.top-tools {
display: flex;
align-items: center;
justify-content: space-between;
max-width: 400px;
margin: 0 auto;
padding: 0 1.25rem;
margin-bottom: 5rem;
.dark-mode {
transform: scale(0.6);
z-index: 2;
}
.top-logo {
display: flex;
justify-content: center;
align-items: center;
z-index: 1;
img {
display: block;
width: 100%;
max-width: 50px;
margin: 0 auto;
}
.iconify {
height: 50px;
width: 50px;
}
}
}
.is-image {
position: relative;
border-inline-end: 1px solid var(--fade-grey);
.hero-image {
position: relative;
z-index: 2;
display: block;
margin: -80px auto 0;
max-width: 60%;
width: 60%;
}
}
.is-form {
position: relative;
max-width: 400px;
margin: 0 auto;
form {
animation: fadeInLeft 0.5s;
}
.form-text {
padding: 0 20px;
animation: fadeInLeft 0.5s;
h2 {
font-family: var(--font-alt);
font-weight: 400;
font-size: 2rem;
color: var(--primary);
}
p {
color: var(--muted-grey);
margin-top: 10px;
}
}
.recover-text {
font-size: 0.9rem;
color: var(--dark-text);
}
.login-wrapper {
padding: 30px 20px;
.control {
position: relative;
width: 100%;
margin-top: 16px;
.input {
padding-top: 14px;
height: 60px;
border-radius: 10px;
padding-inline-start: 55px;
transition: all 0.3s; // transition-all test
&:focus {
background: color-mix(in oklab, var(--fade-grey), white 6%);
border-color: var(--placeholder);
~ .auth-label,
~ .autv-icon .iconify {
color: var(--muted-grey);
}
}
}
.error-text {
color: var(--danger);
font-size: 0.8rem;
display: none;
padding: 2px 6px;
}
.auth-label {
position: absolute;
top: 6px;
inset-inline-start: 55px;
font-size: 0.8rem;
color: var(--dark-text);
font-weight: 500;
z-index: 2;
transition: all 0.3s; // transition-all test
}
.autv-icon,
:deep(.autv-icon) {
position: absolute;
top: 0;
inset-inline-start: 0;
height: 60px;
width: 60px;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: var(--placeholder);
transition: all 0.3s;
}
&.has-validation {
.validation-icon {
position: absolute;
top: 0;
inset-inline-end: 0;
height: 60px;
width: 60px;
display: none;
justify-content: center;
align-items: center;
.icon-wrapper {
height: 20px;
width: 20px;
display: flex;
justify-content: center;
align-items: center;
border-radius: var(--radius-rounded);
.iconify {
height: 10px;
width: 10px;
stroke-width: 3px;
color: var(--white);
}
}
&.is-success {
.icon-wrapper {
background: var(--success);
}
}
&.is-error {
.icon-wrapper {
background: var(--danger);
}
}
}
&.has-success {
.validation-icon {
&.is-success {
display: flex;
}
&.is-error {
display: none;
}
}
}
&.has-error {
.input {
border-color: var(--danger);
}
.error-text {
display: block;
}
.validation-icon {
&.is-error {
display: flex;
}
&.is-success {
display: none;
}
}
}
}
&.is-flex {
display: flex;
align-items: center;
a {
display: block;
margin-inline-start: auto;
color: var(--muted-grey);
font-weight: 500;
font-size: 0.9rem;
transition: color 0.3s;
&:hover,
&:focus {
color: var(--primary);
}
}
.remember-me {
font-size: 0.9rem;
color: var(--muted-grey);
font-weight: 500;
}
}
}
.button-wrap {
margin: 40px 0;
&.has-help {
display: flex;
align-items: center;
> span {
margin-inline-start: 12px;
font-family: var(--font);
a {
color: var(--primary);
font-weight: 500;
padding: 0 2px;
}
}
}
.button {
height: 46px;
width: 140px;
margin-inline-start: 6px;
&:first-child {
&:hover {
opacity: 0.8;
}
}
}
}
}
}
}
.remember-toggle {
width: 65px;
display: block;
position: relative;
cursor: pointer;
font-size: 22px;
user-select: none;
transform: scale(0.9);
input {
position: absolute;
opacity: 0;
cursor: pointer;
&:checked ~ .toggler {
border-color: var(--primary);
.active,
.inactive {
transform: translateX(calc(var(--transform-direction) * 100%)) rotate(360deg);
}
.active {
opacity: 1;
}
.inactive {
opacity: 0;
}
}
}
.toggler {
position: relative;
display: block;
height: 34px;
width: 61px;
border: 2px solid var(--placeholder);
border-radius: 100px;
transition: all 0.3s; // transition-all test
.active,
.inactive {
position: absolute;
top: 2px;
inset-inline-start: 2px;
height: 26px;
width: 26px;
border-radius: var(--radius-rounded);
background: black;
display: flex;
justify-content: center;
align-items: center;
transform: translateX(calc(var(--transform-direction) * 0))
rotate(calc(var(--transform-direction) * 0));
transition: all 0.3s ease;
.iconify {
color: var(--white);
font-size: 14px;
}
}
.inactive {
background: var(--placeholder);
border-color: var(--placeholder);
opacity: 1;
z-index: 1;
}
.active {
background: var(--primary);
border-color: var(--primary);
opacity: 0;
z-index: 0;
}
}
}
@media only screen and (width <= 767px) {
.modern-login {
.top-logo {
top: 30px;
}
.dark-mode {
top: 36px;
inset-inline-end: 44px;
}
.is-form {
padding-top: 100px;
}
}
}
@media only screen and (width >= 768px) and (width <= 1024px) and (orientation: portrait) {
.modern-login {
.top-logo {
.iconify {
height: 60px;
width: 60px;
}
}
.dark-mode {
top: -58px;
inset-inline-end: 30%;
}
.columns {
display: flex;
height: 100vh;
}
}
}
/* ==========================================================================
Dark mode
========================================================================== */
.is-dark {
.modern-login {
background: var(--dark-sidebar);
.underlay {
background: color-mix(in oklab, var(--dark-sidebar), white 10%);
}
.is-image {
border-color: color-mix(in oklab, var(--dark-sidebar), white 10%);
}
.is-form {
.form-text {
h2 {
color: var(--primary);
}
}
.login-wrapper {
.control {
&.is-flex {
a:hover {
color: var(--primary);
}
}
.input {
background: color-mix(in oklab, var(--dark-sidebar), white 4%);
&:focus {
border-color: var(--primary);
~ .autv-icon {
.iconify {
color: var(--primary);
}
}
}
}
.auth-label {
color: var(--light-text);
}
}
.button-wrap {
&.has-help {
span {
color: var(--light-text);
a {
color: var(--primary);
}
}
}
}
}
}
}
.remember-toggle {
input {
&:checked + .toggler {
border-color: var(--primary);
> span {
background: var(--primary);
}
}
}
.toggler {
border-color: color-mix(in oklab, var(--dark-sidebar), white 12%);
> span {
background: color-mix(in oklab, var(--dark-sidebar), white 12%);
}
}
}
}
</style>

1501
src/pages/auth/signup-1.vue Normal file

File diff suppressed because it is too large Load Diff

256
src/pages/auth/signup-2.vue Normal file
View File

@@ -0,0 +1,256 @@
<script setup lang="ts">
import { toTypedSchema } from '@vee-validate/zod'
import { useForm } from 'vee-validate'
import { z } from 'zod'
const router = useRouter()
const notyf = useNotyf()
const isLoading = ref(false)
const { t } = useI18n()
// This is the Zod schema for the form input
// It's used to define the shape that the form data will have
const zodSchema = z
.object({
name: z
.string({
required_error: t('auth.errors.name.required'),
})
.min(1, t('auth.errors.name.required')),
email: z
.string({
required_error: t('auth.errors.email.required'),
})
.email(t('auth.errors.email.format')),
password: z
.string({
required_error: t('auth.errors.password.required'),
})
.min(8, t('auth.errors.password.length')),
passwordCheck: z.string({
required_error: t('auth.errors.passwordCheck.required'),
}),
promotional: z.boolean(),
})
// Refine is used to add custom validation rules to the schema
.refine(data => data.password === data.passwordCheck, {
message: t('auth.errors.passwordCheck.match'),
path: ['passwordCheck'],
})
// Zod has a great infer method that will
// infer the shape of the schema into a TypeScript type
type FormInput = z.infer<typeof zodSchema>
// Define a validation schema
const validationSchema = toTypedSchema(zodSchema)
// Set initial values for the form
const initialValues = {
name: '',
email: '',
password: '',
passwordCheck: '',
promotional: false,
} satisfies FormInput
// here we create a vee-validate form context that
// will be used in all vuero form components
const { handleSubmit } = useForm({
validationSchema,
initialValues,
})
const onSignup = handleSubmit(async (values) => {
console.log('handleSignup values')
console.table(values)
if (!isLoading.value) {
isLoading.value = true
await sleep(800)
notyf.dismissAll()
notyf.primary('Welcome, Erik Kovalsky')
router.push('/sidebar/dashboards')
isLoading.value = false
}
})
useHead({
title: 'Auth Signup 2 - Vuero',
})
</script>
<template>
<div class="auth-wrapper-inner columns is-gapless">
<!-- Form section -->
<div class="column is-5">
<div class="hero is-fullheight is-white">
<div class="hero-heading">
<div class="auth-logo">
<LanguageDropdown />
<RouterLink to="/">
<AnimatedLogo
class="top-logo"
width="36px"
height="36px"
/>
</RouterLink>
<VDarkmodeToggle />
</div>
</div>
<div class="hero-body">
<div class="container">
<div class="columns">
<div class="column is-12">
<div class="auth-content">
<h2>{{ t('auth.title') }}</h2>
<p>{{ t('auth.subtitle') }}</p>
<RouterLink to="/auth/login-2">
{{ t('auth.action.login') }}
</RouterLink>
</div>
<div class="auth-form-wrapper">
<!-- Login Form -->
<form
method="post"
novalidate
@submit="onSignup"
>
<div class="login-form">
<!-- Input -->
<VField
id="name"
v-slot="{ field }"
>
<VControl icon="lucide:user">
<VInput
type="text"
:placeholder="t('auth.placeholder.name')"
autocomplete="name"
/>
<p
v-if="field?.errorMessage"
class="help is-danger"
>
{{ field.errorMessage }}
</p>
</VControl>
</VField>
<!-- Input -->
<VField
id="email"
v-slot="{ field }"
>
<VControl icon="lucide:mail">
<VInput
type="text"
:placeholder="t('auth.placeholder.email')"
autocomplete="email"
/>
<p
v-if="field?.errorMessage"
class="help is-danger"
>
{{ field.errorMessage }}
</p>
</VControl>
</VField>
<!-- Input -->
<VField
id="password"
v-slot="{ field }"
>
<VControl icon="lucide:lock">
<VInput
type="password"
:placeholder="t('auth.placeholder.password')"
autocomplete="new-password"
/>
<p
v-if="field?.errorMessage"
class="help is-danger"
>
{{ field.errorMessage }}
</p>
</VControl>
</VField>
<!-- Input -->
<VField
id="passwordCheck"
v-slot="{ field }"
>
<VControl icon="lucide:lock">
<VInput
type="password"
:placeholder="t('auth.placeholder.passwordCheck')"
/>
<p
v-if="field?.errorMessage"
class="help is-danger"
>
{{ field.errorMessage }}
</p>
</VControl>
</VField>
<VField id="promitional">
<VControl class="setting-item">
<VCheckbox
color="primary"
:label="t('auth.label.promotional')"
paddingless
/>
</VControl>
</VField>
<!-- Submit -->
<div class="login">
<VButton
type="submit"
color="primary"
bold
fullwidth
raised
>
{{ t('auth.action.signup') }}
</VButton>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Image section (hidden on mobile) -->
<div class="column login-column is-7 is-hidden-mobile hero-banner">
<div class="hero login-hero is-fullheight is-app-grey">
<div class="hero-body is-justify-content-center is-fullwidth">
<div class="is-flex is-justify-content-center is-fullwidth">
<img
class="light-image has-light-shadow has-light-border"
src="/images/illustrations/apps/vuero-banking-light.webp"
alt=""
>
<img
class="dark-image has-light-shadow"
src="/images/illustrations/apps/vuero-banking-dark.webp"
alt=""
>
</div>
</div>
</div>
</div>
</div>
</template>

133
src/pages/auth/signup-3.vue Normal file
View File

@@ -0,0 +1,133 @@
<script setup lang="ts">
const router = useRouter()
const notyf = useNotyf()
const isLoading = ref(false)
const handleSignup = async () => {
if (!isLoading.value) {
isLoading.value = true
sleep(2000)
notyf.dismissAll()
notyf.primary('Welcome, Erik Kovalsky')
router.push('/sidebar/dashboards')
isLoading.value = false
}
}
useHead({
title: 'Auth Signup 3 - Vuero',
})
</script>
<template>
<div class="auth-wrapper-inner is-single">
<LandingGrids class="is-contrasted" />
<!--Fake navigation-->
<div class="auth-nav">
<div class="left" />
<div class="center">
<RouterLink
to="/"
class="header-item"
>
<AnimatedLogo
width="38px"
height="38px"
/>
</RouterLink>
</div>
<div class="right">
<VDarkmodeToggle />
</div>
</div>
<!--Single Centered Form-->
<div class="single-form-wrap is-relative">
<div class="inner-wrap">
<!--Form Title-->
<div class="auth-head">
<h2>Join Us Now.</h2>
<p>Start by creating your account</p>
<RouterLink to="/auth/login-3">
I already have an account
</RouterLink>
</div>
<!--Form-->
<div class="form-card">
<form
method="post"
novalidate
@submit.prevent="handleSignup"
>
<div class="login-form">
<!-- Input -->
<VField>
<VControl icon="lucide:user">
<VInput
type="text"
placeholder="Name"
autocomplete="name"
/>
</VControl>
</VField>
<!-- Input -->
<VField>
<VControl icon="lucide:mail">
<VInput
type="text"
placeholder="Email Address"
autocomplete="email"
/>
</VControl>
</VField>
<!-- Input -->
<VField>
<VControl icon="lucide:lock">
<VInput
type="password"
placeholder="Password"
autocomplete="new-password"
/>
</VControl>
</VField>
<!-- Input -->
<VField>
<VControl icon="lucide:lock">
<VInput
type="password"
placeholder="Repeat Password"
/>
</VControl>
</VField>
<VField>
<VControl class="setting-item">
<VCheckbox
label="Receive promotional offers"
color="primary"
paddingless
/>
</VControl>
</VField>
<!-- Submit -->
<div class="login">
<VButton
color="primary"
type="submit"
bold
fullwidth
raised
>
Sign Up
</VButton>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</template>

View File