mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-24 18:03:06 +02:00
Refactor account pages
This commit is contained in:
85
src/components/AccountSidebar.astro
Normal file
85
src/components/AccountSidebar.astro
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
import Icon from './AstroIcon.astro';
|
||||
|
||||
const { activePageId, activePageTitle } = Astro.props;
|
||||
|
||||
export interface Props {
|
||||
activePageId: string;
|
||||
activePageTitle: string;
|
||||
}
|
||||
---
|
||||
|
||||
<div class='relative block mb-5 md:hidden p-4 border-b shadow-inner'>
|
||||
<button
|
||||
class='flex h-10 w-full items-center justify-between rounded-md border bg-white px-2 text-center font-medium text-gray-900'
|
||||
id='settings-menu'
|
||||
>
|
||||
{activePageTitle}
|
||||
<Icon icon='dropdown' />
|
||||
</button>
|
||||
<ul
|
||||
id='settings-menu-dropdown'
|
||||
class='absolute mt-1 hidden left-0 right-0 space-y-1.5 bg-white p-2 shadow-lg z-10'
|
||||
>
|
||||
<li>
|
||||
<a
|
||||
href='/account/update-profile'
|
||||
class=`block w-full rounded px-2 py-1.5 font-medium text-slate-900 hover:bg-slate-200 ${activePageId === 'profile' ? 'bg-slate-100' : ''}`
|
||||
>Profile</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href='/account/update-password'
|
||||
class=`block w-full rounded px-2 py-1.5 font-medium text-slate-900 hover:bg-slate-200 ${activePageId === 'change-password' ? 'bg-slate-100' : ''}`
|
||||
>Change password</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class='container flex min-h-screen items-stretch'>
|
||||
<!-- Start Desktop Sidebar -->
|
||||
<aside class='hidden w-56 border-r border-slate-200 py-10 pr-5 md:block'>
|
||||
<nav>
|
||||
<ul class='space-y-1'>
|
||||
<li>
|
||||
<a
|
||||
href='/account/update-profile'
|
||||
class=`block w-full rounded px-2 py-1.5 font-regular text-slate-900 hover:bg-slate-100 ${activePageId === 'profile' ? 'bg-slate-100' : ''}`
|
||||
>
|
||||
Profile
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href='/account/update-password'
|
||||
class=`block w-full rounded px-2 py-1.5 font-regular text-slate-900 hover:bg-slate-100 ${activePageId === 'change-password' ? 'bg-slate-100' : ''}`
|
||||
>
|
||||
Security
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
<!-- /End Desktop Sidebar -->
|
||||
|
||||
<div class='grow px-0 py-0 md:px-10 md:py-10'>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const menuButton = document.getElementById('settings-menu');
|
||||
const menuDropdown = document.getElementById('settings-menu-dropdown');
|
||||
|
||||
menuButton?.addEventListener('click', () => {
|
||||
menuDropdown?.classList.toggle('hidden');
|
||||
});
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!menuButton?.contains(e.target as Node)) {
|
||||
menuDropdown?.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
</script>
|
@@ -32,8 +32,8 @@ function showHideGuestElements(hideOrShow: 'hide' | 'show' = 'hide') {
|
||||
// Prepares the UI for the user who is logged in
|
||||
function handleGuest() {
|
||||
const authenticatedRoutes = [
|
||||
'/settings/update-profile',
|
||||
'/settings/update-password',
|
||||
'/account/update-profile',
|
||||
'/account/update-password',
|
||||
];
|
||||
|
||||
showHideAuthElements('hide');
|
||||
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
---
|
||||
|
||||
<div class='recaptcha-field mb-2'></div>
|
||||
<input type='hidden' name='g-recaptcha-response' class='recaptcha-response' />
|
@@ -1,36 +0,0 @@
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
<script src='./captcha.js'></script>
|
||||
|
||||
<script is:inline>
|
||||
window.onCaptchaLoad = function () {
|
||||
if (!window.grecaptcha) {
|
||||
console.warn('window.grecaptcha is not defined');
|
||||
return;
|
||||
}
|
||||
|
||||
const recaptchaFields = document.querySelectorAll('.recaptcha-field');
|
||||
|
||||
// render recaptcha on fields
|
||||
recaptchaFields.forEach((field) => {
|
||||
// If captcha already rendered for this field
|
||||
if (field.hasAttribute('data-recaptcha-id')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const renderedId = window.grecaptcha.render(field, {
|
||||
sitekey: '6Ldn2YsjAAAAABlUxNxukAuDAUIuZIhO0hRVxzJW',
|
||||
});
|
||||
|
||||
field.setAttribute('data-recaptcha-id', renderedId);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<script
|
||||
src='https://www.google.com/recaptcha/api.js?onload=onCaptchaLoad&render=explicit'
|
||||
async
|
||||
defer
|
||||
></script>
|
@@ -1,49 +0,0 @@
|
||||
class Captcha {
|
||||
constructor() {
|
||||
this.onDOMLoaded = this.onDOMLoaded.bind(this);
|
||||
this.bindValidation = this.bindValidation.bind(this);
|
||||
this.validateCaptchaBeforeSubmit =
|
||||
this.validateCaptchaBeforeSubmit.bind(this);
|
||||
}
|
||||
|
||||
validateCaptchaBeforeSubmit(e) {
|
||||
const target = e.target;
|
||||
const captchaField = target.querySelector('.recaptcha-field');
|
||||
|
||||
if (captchaField) {
|
||||
const captchaId = captchaField.dataset.recaptchaId;
|
||||
const captchaResponse = window.grecaptcha.getResponse(captchaId);
|
||||
|
||||
// If valid captcha is not present, prevent form submission
|
||||
if (!captchaResponse) {
|
||||
e.preventDefault();
|
||||
alert('Please verify that you are human first');
|
||||
return false;
|
||||
}
|
||||
|
||||
target.querySelector('.recaptcha-response').value = captchaResponse;
|
||||
}
|
||||
|
||||
target.closest('.popup').classList.add('hidden');
|
||||
return true;
|
||||
}
|
||||
|
||||
bindValidation() {
|
||||
const forms = document.querySelectorAll('[captcha-form]');
|
||||
|
||||
forms.forEach((form) => {
|
||||
form.addEventListener('submit', this.validateCaptchaBeforeSubmit);
|
||||
});
|
||||
}
|
||||
|
||||
onDOMLoaded() {
|
||||
this.bindValidation();
|
||||
}
|
||||
|
||||
init() {
|
||||
window.addEventListener('DOMContentLoaded', this.onDOMLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
const captcha = new Captcha();
|
||||
captcha.init();
|
@@ -1,14 +1,14 @@
|
||||
import { useEffect, useRef, useState } from 'preact/hooks';
|
||||
import { useKeydown } from '../../hooks/use-keydown';
|
||||
import { useOutsideClick } from '../../hooks/use-outside-click';
|
||||
import BestPracticesIcon from '../../icons/best-practices.svg';
|
||||
import HomeIcon from '../../icons/home.svg';
|
||||
import UserIcon from '../../icons/user.svg';
|
||||
import RoadmapIcon from '../../icons/roadmap.svg';
|
||||
import GuideIcon from '../../icons/guide.svg';
|
||||
import HomeIcon from '../../icons/home.svg';
|
||||
import RoadmapIcon from '../../icons/roadmap.svg';
|
||||
import UserIcon from '../../icons/user.svg';
|
||||
import VideoIcon from '../../icons/video.svg';
|
||||
import { httpGet } from '../../lib/http';
|
||||
import { useKeydown } from '../../hooks/use-keydown';
|
||||
import { isLoggedIn } from '../../lib/jwt';
|
||||
import { useOutsideClick } from '../../hooks/use-outside-click';
|
||||
|
||||
type PageType = {
|
||||
url: string;
|
||||
@@ -21,7 +21,7 @@ type PageType = {
|
||||
const defaultPages: PageType[] = [
|
||||
{ url: '/', title: 'Home', group: 'Pages', icon: HomeIcon },
|
||||
{
|
||||
url: '/settings/update-profile',
|
||||
url: '/account/update-profile',
|
||||
title: 'Account',
|
||||
group: 'Pages',
|
||||
icon: UserIcon,
|
||||
|
@@ -24,7 +24,7 @@ import Icon from '../AstroIcon.astro';
|
||||
<ul>
|
||||
<li class='px-1'>
|
||||
<a
|
||||
href='/settings/update-profile'
|
||||
href='/account/update-profile'
|
||||
class='block rounded px-4 py-2 text-sm font-medium text-slate-100 hover:bg-slate-700'
|
||||
>
|
||||
Settings
|
||||
|
@@ -98,7 +98,7 @@ import AccountDropdown from './AccountDropdown.astro';
|
||||
<!-- Links for logged in users -->
|
||||
<li data-auth-required class='hidden'>
|
||||
<a
|
||||
href='/settings/update-profile'
|
||||
href='/account/update-profile'
|
||||
class='text-xl hover:text-blue-300 md:text-lg'
|
||||
>
|
||||
Settings
|
||||
|
@@ -1,81 +0,0 @@
|
||||
---
|
||||
import Icon from '../AstroIcon.astro';
|
||||
const { pageUrl, name } = Astro.props;
|
||||
|
||||
export interface Props {
|
||||
pageUrl: string;
|
||||
name: string;
|
||||
}
|
||||
---
|
||||
|
||||
<div
|
||||
class='container flex min-h-[calc(100vh-37px-70px)] items-stretch sm:min-h-[calc(100vh-37px-96px)]'
|
||||
>
|
||||
<aside class='hidden w-56 border-r border-slate-200 py-10 pr-5 md:block'>
|
||||
<nav>
|
||||
<ul class='space-y-1'>
|
||||
<li>
|
||||
<a
|
||||
href='/settings/update-profile'
|
||||
class=`block w-full rounded px-2 py-1.5 font-regular text-slate-900 hover:bg-slate-100 ${pageUrl === 'profile' ? 'bg-slate-100' : ''}`
|
||||
>Profile</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href='/settings/update-password'
|
||||
class=`block w-full rounded px-2 py-1.5 font-regular text-slate-900 hover:bg-slate-100 ${pageUrl === 'change-password' ? 'bg-slate-100' : ''}`
|
||||
>Security</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
<div class='grow py-10 pl-0 md:p-10 md:pr-0'>
|
||||
<div class='relative mb-5 md:hidden'>
|
||||
<button
|
||||
class='flex h-10 w-full items-center justify-between rounded-md bg-slate-800 px-2 text-center font-medium text-slate-100'
|
||||
id='settings-menu'
|
||||
>
|
||||
{name}
|
||||
<Icon icon='dropdown' />
|
||||
</button>
|
||||
<ul
|
||||
id='settings-menu-dropdown'
|
||||
class='absolute mt-1 hidden w-full space-y-1.5 rounded-md bg-white p-2 shadow-lg'
|
||||
>
|
||||
<li>
|
||||
<a
|
||||
href='/settings/update-profile'
|
||||
class=`block w-full rounded px-2 py-1.5 font-medium text-slate-900 hover:bg-slate-200 ${pageUrl === 'profile' ? 'bg-slate-100' : ''}`
|
||||
>Profile</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href='/settings/update-password'
|
||||
class=`block w-full rounded px-2 py-1.5 font-medium text-slate-900 hover:bg-slate-200 ${pageUrl === 'change-password' ? 'bg-slate-100' : ''}`
|
||||
>Change password</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const menuButton = document.getElementById('settings-menu');
|
||||
const menuDropdown = document.getElementById('settings-menu-dropdown');
|
||||
|
||||
menuButton?.addEventListener('click', () => {
|
||||
menuDropdown?.classList.toggle('hidden');
|
||||
});
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!menuButton?.contains(e.target as Node)) {
|
||||
menuDropdown?.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
</script>
|
@@ -78,9 +78,11 @@ export default function UpdatePasswordForm() {
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<h2 className="text-3xl font-bold sm:text-4xl">Password</h2>
|
||||
<p className="mt-2">Use the form below to update your password.</p>
|
||||
<div className="mt-8 space-y-4">
|
||||
<div class="hidden md:block mb-8">
|
||||
<h2 className="text-3xl font-bold sm:text-4xl">Password</h2>
|
||||
<p className="mt-2">Use the form below to update your password.</p>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
{authProvider === 'email' && (
|
||||
<div className="flex w-full flex-col">
|
||||
<label
|
||||
@@ -132,7 +134,7 @@ export default function UpdatePasswordForm() {
|
||||
for="new-password-confirmation"
|
||||
className="text-sm leading-none text-slate-500"
|
||||
>
|
||||
New Password Confirm
|
||||
Confirm New Password
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
@@ -141,7 +143,7 @@ export default function UpdatePasswordForm() {
|
||||
className="mt-2 block w-full rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
|
||||
required
|
||||
minLength={6}
|
||||
placeholder="New password confirm"
|
||||
placeholder="Confirm New Password"
|
||||
value={newPasswordConfirmation}
|
||||
onInput={(e) =>
|
||||
setNewPasswordConfirmation((e.target as HTMLInputElement).value)
|
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState } from 'preact/hooks';
|
||||
import { httpGet, httpPost } from '../../lib/http';
|
||||
import { pageLoadingMessage } from '../../stores/page';
|
||||
import UploadProfilePicture from '../Profile/UploadProfilePicture';
|
||||
import UploadProfilePicture from './UploadProfilePicture';
|
||||
|
||||
export function UpdateProfileForm() {
|
||||
const [name, setName] = useState('');
|
||||
@@ -81,8 +81,10 @@ export function UpdateProfileForm() {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 className="text-3xl font-bold sm:text-4xl">Profile</h2>
|
||||
<p className="mt-2">Update your profile details below.</p>
|
||||
<div className="mb-8 hidden md:block">
|
||||
<h2 className="text-3xl font-bold sm:text-4xl">Profile</h2>
|
||||
<p className="mt-2">Update your profile details below.</p>
|
||||
</div>
|
||||
<UploadProfilePicture
|
||||
avatarUrl={
|
||||
avatar
|
@@ -1,7 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'preact/hooks';
|
||||
import Cookies from 'js-cookie';
|
||||
import { useEffect, useRef, useState } from 'preact/hooks';
|
||||
import { TOKEN_COOKIE_NAME } from '../../lib/jwt';
|
||||
import { httpCall, httpPost } from '../../lib/http';
|
||||
|
||||
interface PreviewFile extends File {
|
||||
preview: string;
|
||||
@@ -131,7 +130,7 @@ export default function UploadProfilePicture(props: UploadProfilePictureProps) {
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
encType="multipart/form-data"
|
||||
className="mt-8 flex flex-col gap-2"
|
||||
className="flex flex-col gap-2"
|
||||
>
|
||||
<label htmlFor="avatar" className="text-sm leading-none text-slate-500">
|
||||
Profile Picture
|
16
src/pages/account/update-password.astro
Normal file
16
src/pages/account/update-password.astro
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
import AccountSidebar from '../../components/AccountSidebar.astro';
|
||||
import UpdatePasswordForm from '../../components/UpdatePassword/UpdatePasswordForm';
|
||||
import AccountLayout from '../../layouts/AccountLayout.astro';
|
||||
---
|
||||
|
||||
<AccountLayout
|
||||
title='Change Password'
|
||||
description=''
|
||||
noIndex={true}
|
||||
initialLoadingMessage={'Loading profile'}
|
||||
>
|
||||
<AccountSidebar activePageId='change-password' activePageTitle='Change Password'>
|
||||
<UpdatePasswordForm client:load />
|
||||
</AccountSidebar>
|
||||
</AccountLayout>
|
15
src/pages/account/update-profile.astro
Normal file
15
src/pages/account/update-profile.astro
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
import AccountSidebar from '../../components/AccountSidebar.astro';
|
||||
import { UpdateProfileForm } from '../../components/UpdateProfile/UpdateProfileForm';
|
||||
import AccountLayout from '../../layouts/AccountLayout.astro';
|
||||
---
|
||||
|
||||
<AccountLayout
|
||||
title='Update Profile'
|
||||
noIndex={true}
|
||||
initialLoadingMessage={'Loading profile'}
|
||||
>
|
||||
<AccountSidebar activePageId='profile' activePageTitle='Profile'>
|
||||
<UpdateProfileForm client:load />
|
||||
</AccountSidebar>
|
||||
</AccountLayout>
|
@@ -1,9 +1,9 @@
|
||||
---
|
||||
import { ForgotPasswordForm } from '../components/AuthenticationFlow/ForgotPasswordForm';
|
||||
import SettingLayout from '../layouts/SettingLayout.astro';
|
||||
import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
---
|
||||
|
||||
<SettingLayout title='Forgot Password' noIndex={true}>
|
||||
<AccountLayout title='Forgot Password' noIndex={true}>
|
||||
<div class='container'>
|
||||
<div
|
||||
class='mx-auto flex flex-col items-start justify-start pb-28 pt-10 sm:max-w-[400px] sm:items-center sm:justify-center sm:pt-20'
|
||||
@@ -29,4 +29,4 @@ import SettingLayout from '../layouts/SettingLayout.astro';
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SettingLayout>
|
||||
</AccountLayout>
|
||||
|
@@ -1,12 +1,12 @@
|
||||
---
|
||||
import Divider from '../components/AuthenticationFlow/Divider.astro';
|
||||
import EmailLoginForm from '../components/AuthenticationFlow/EmailLoginForm';
|
||||
import { GitHubButton } from '../components/AuthenticationFlow/GitHubButton';
|
||||
import { GoogleButton } from '../components/AuthenticationFlow/GoogleButton';
|
||||
import EmailLoginForm from '../components/AuthenticationFlow/EmailLoginForm';
|
||||
import SettingLayout from '../layouts/SettingLayout.astro';
|
||||
import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
---
|
||||
|
||||
<SettingLayout
|
||||
<AccountLayout
|
||||
title='Login - roadmap.sh'
|
||||
description='Register yourself to receive occasional emails about new roadmaps, updates, guides and videos'
|
||||
permalink={'/signup'}
|
||||
@@ -38,4 +38,4 @@ import SettingLayout from '../layouts/SettingLayout.astro';
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SettingLayout>
|
||||
</AccountLayout>
|
||||
|
@@ -1,9 +1,9 @@
|
||||
---
|
||||
import ResetPasswordForm from '../components/AuthenticationFlow/ResetPasswordForm';
|
||||
import SettingLayout from '../layouts/SettingLayout.astro';
|
||||
import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
---
|
||||
|
||||
<SettingLayout title='Reset Password' noIndex={true}>
|
||||
<AccountLayout title='Reset Password' noIndex={true}>
|
||||
<div class='container'>
|
||||
<div
|
||||
class='mx-auto flex flex-col items-start justify-start pb-28 pt-10 sm:max-w-[400px] sm:items-center sm:justify-center sm:pt-20'
|
||||
@@ -20,4 +20,4 @@ import SettingLayout from '../layouts/SettingLayout.astro';
|
||||
<ResetPasswordForm client:load />
|
||||
</div>
|
||||
</div>
|
||||
</SettingLayout>
|
||||
</AccountLayout>
|
||||
|
@@ -1,16 +0,0 @@
|
||||
---
|
||||
import SettingSidebar from '../../components/Setting/SettingSidebar.astro';
|
||||
import UpdatePasswordForm from '../../components/Setting/UpdatePasswordForm';
|
||||
import SettingLayout from '../../layouts/SettingLayout.astro';
|
||||
---
|
||||
|
||||
<SettingLayout
|
||||
title='Change Password'
|
||||
description=''
|
||||
noIndex={true}
|
||||
initialLoadingMessage={'Loading profile'}
|
||||
>
|
||||
<SettingSidebar pageUrl='change-password' name='Change Password'>
|
||||
<UpdatePasswordForm client:load />
|
||||
</SettingSidebar>
|
||||
</SettingLayout>
|
@@ -1,15 +0,0 @@
|
||||
---
|
||||
import SettingSidebar from '../../components/Setting/SettingSidebar.astro';
|
||||
import { UpdateProfileForm } from '../../components/Setting/UpdateProfileForm';
|
||||
import SettingLayout from '../../layouts/SettingLayout.astro';
|
||||
---
|
||||
|
||||
<SettingLayout
|
||||
title='Update Profile'
|
||||
noIndex={true}
|
||||
initialLoadingMessage={'Loading profile'}
|
||||
>
|
||||
<SettingSidebar pageUrl='profile' name='Profile'>
|
||||
<UpdateProfileForm client:load />
|
||||
</SettingSidebar>
|
||||
</SettingLayout>
|
@@ -1,13 +1,12 @@
|
||||
---
|
||||
import Divider from '../components/AuthenticationFlow/Divider.astro';
|
||||
import GoogleLogin from '../components/Login/GoogleLogin.astro';
|
||||
import EmailSignupForm from '../components/AuthenticationFlow/EmailSignupForm';
|
||||
import SettingLayout from '../layouts/SettingLayout.astro';
|
||||
import { GitHubButton } from '../components/AuthenticationFlow/GitHubButton';
|
||||
import { GoogleButton } from '../components/AuthenticationFlow/GoogleButton';
|
||||
import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
---
|
||||
|
||||
<SettingLayout
|
||||
<AccountLayout
|
||||
title='Signup - roadmap.sh'
|
||||
description='Create an account to track your progress, showcase your skillset'
|
||||
permalink={'/signup'}
|
||||
@@ -46,4 +45,4 @@ import { GoogleButton } from '../components/AuthenticationFlow/GoogleButton';
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SettingLayout>
|
||||
</AccountLayout>
|
||||
|
@@ -1,10 +1,10 @@
|
||||
---
|
||||
import { VerificationEmailMessage } from '../components/AuthenticationFlow/VerificationEmailMessage';
|
||||
import SettingLayout from '../layouts/SettingLayout.astro';
|
||||
import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
---
|
||||
|
||||
<SettingLayout title='Verify Email' noIndex={true}>
|
||||
<AccountLayout title='Verify Email' noIndex={true}>
|
||||
<section class='container py-8 sm:py-20'>
|
||||
<VerificationEmailMessage client:load />
|
||||
</section>
|
||||
</SettingLayout>
|
||||
</AccountLayout>
|
||||
|
@@ -1,10 +1,10 @@
|
||||
---
|
||||
import { TriggerVerifyAccount } from '../components/AuthenticationFlow/TriggerVerifyAccount';
|
||||
import SettingLayout from '../layouts/SettingLayout.astro';
|
||||
import AccountLayout from '../layouts/AccountLayout.astro';
|
||||
---
|
||||
|
||||
<SettingLayout title='Verify account' noIndex={true}>
|
||||
<AccountLayout title='Verify account' noIndex={true}>
|
||||
<div class='container py-16'>
|
||||
<TriggerVerifyAccount client:load />
|
||||
</div>
|
||||
</SettingLayout>
|
||||
</AccountLayout>
|
||||
|
Reference in New Issue
Block a user