update
This commit is contained in:
parent
ef00b108f1
commit
b354fafeaf
18 changed files with 586 additions and 173 deletions
|
@ -8,5 +8,10 @@ export default defineConfig({
|
||||||
}),
|
}),
|
||||||
security: {
|
security: {
|
||||||
checkOrigin: true,
|
checkOrigin: true,
|
||||||
|
},
|
||||||
|
vite: {
|
||||||
|
server: {
|
||||||
|
hmr: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
|
@ -1,6 +1,8 @@
|
||||||
---
|
---
|
||||||
if (Astro.cookies.get('sb-access-token') && Astro.cookies.get('sb-refresh-token')) {
|
if (Astro.cookies.get('sb-access-token') && Astro.cookies.get('sb-refresh-token')) {
|
||||||
var IsLoggedIn = true
|
var IsLoggedIn = true
|
||||||
|
} else if (Astro.cookies.get('anonymous-session')) {
|
||||||
|
var IsLoggedIn = true
|
||||||
} else {
|
} else {
|
||||||
var IsLoggedIn = false
|
var IsLoggedIn = false
|
||||||
}
|
}
|
||||||
|
@ -17,15 +19,15 @@ const beta = user?.user_metadata.beta
|
||||||
<h2><a href="/">Supabase Demo</a> {beta ? <span>Beta</span> : null}</h2>
|
<h2><a href="/">Supabase Demo</a> {beta ? <span>Beta</span> : null}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-end">
|
<div class="header-end">
|
||||||
{IsLoggedIn
|
{IsLoggedIn
|
||||||
?
|
?
|
||||||
<img src={avatar}/>
|
<img src={avatar}/>
|
||||||
<a href="/account">Account</a>
|
<a href="/account">Account</a>
|
||||||
<a href="/api/auth/signout">Sign Out</a>
|
<a href="/api/auth/signout">Sign Out</a>
|
||||||
:
|
:
|
||||||
<a href="/register">Register</a>
|
<a href="/register">Register</a>
|
||||||
<a href="/signin">Sign in</a>
|
<a href="/signin">Sign in</a>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|
21
src/components/QuickForm.astro
Normal file
21
src/components/QuickForm.astro
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
const {
|
||||||
|
Action,
|
||||||
|
Method,
|
||||||
|
Label,
|
||||||
|
Name,
|
||||||
|
Type,
|
||||||
|
Value,
|
||||||
|
Button
|
||||||
|
} = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<form action={Action} method={Method} class="quick-input-form">
|
||||||
|
<div>
|
||||||
|
<label>{Label}</label>
|
||||||
|
<div class="qif-input-w-button">
|
||||||
|
<input id={Name} type={Type} name={Name} value={Value}/>
|
||||||
|
<button type="submit">{Button}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
9
src/components/QuickFormButton.astro
Normal file
9
src/components/QuickFormButton.astro
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
const {
|
||||||
|
Action,
|
||||||
|
Method,
|
||||||
|
Button
|
||||||
|
} = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<form action={Action} method={Method} class="quick-input-button"><button type="submit">{Button}</button></form>
|
115
src/layouts/Settings.astro
Normal file
115
src/layouts/Settings.astro
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
---
|
||||||
|
const {Title} = Astro.props
|
||||||
|
import Head from "@components/Head.astro"
|
||||||
|
import Header from "@components/Header.astro"
|
||||||
|
import '@styles/root.scss'
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<Head Title={Title}/>
|
||||||
|
<Header/>
|
||||||
|
<body>
|
||||||
|
<div transition:animate="fade" class="content">
|
||||||
|
<div class="settings-panel">
|
||||||
|
<div class="sp-sidebar">
|
||||||
|
<a id="sb-s-account" href="/account">Account</a>
|
||||||
|
<a id="sb-s-preferences" href="/account/preferences">Preferences</a>
|
||||||
|
<a id="sb-s-resetpassword" href="#">Reset Password</a>
|
||||||
|
<hr/>
|
||||||
|
<a id="sb-s-beta" href="/account/beta">Beta</a>
|
||||||
|
<a id="sb-s-advance" href="#">Advance</a>
|
||||||
|
</div>
|
||||||
|
<div class="sp-content">
|
||||||
|
<slot/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<style lang="scss" is:global>
|
||||||
|
.settings-panel {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 160px auto;
|
||||||
|
gap: 24px;
|
||||||
|
.sp-sidebar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
a {
|
||||||
|
background: transparent;
|
||||||
|
color: white;
|
||||||
|
border: 1px transparent solid;
|
||||||
|
transition: 0.3s border-color;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 14px;
|
||||||
|
&:hover {
|
||||||
|
border-color: white;
|
||||||
|
transition: 1s border-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.account-info-cet {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
* {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-input-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px rgb(49, 49, 49) solid;
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 4px 0px 0px 4px;
|
||||||
|
&:hover {
|
||||||
|
border-color: rgb(145, 145, 145);
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
border-color: white;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.qif-input-w-button {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
button {
|
||||||
|
color: white;
|
||||||
|
background: rgb(49, 49, 49);
|
||||||
|
border-radius: 0px 4px 4px 0px;
|
||||||
|
&:hover {
|
||||||
|
background: rgb(145, 145, 145);
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
color: black;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -47,7 +47,7 @@ export const onRequest = defineMiddleware(
|
||||||
const refreshToken = cookies.get("sb-refresh-token")
|
const refreshToken = cookies.get("sb-refresh-token")
|
||||||
|
|
||||||
if (accessToken && refreshToken) {
|
if (accessToken && refreshToken) {
|
||||||
return redirect("/dashboard")
|
return redirect("/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return next()
|
return next()
|
||||||
|
|
57
src/pages/account/beta.astro
Normal file
57
src/pages/account/beta.astro
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
---
|
||||||
|
import QuickForm from "@components/QuickForm.astro"
|
||||||
|
import QuickFormButton from "@components/QuickFormButton.astro"
|
||||||
|
import Settings from "@layouts/Settings.astro"
|
||||||
|
|
||||||
|
// Supabase Data
|
||||||
|
import { supabase } from "@library/supabase"
|
||||||
|
const { data: { user } } = await supabase.auth.getUser()
|
||||||
|
const avatarUrl = user?.user_metadata.avatar_url
|
||||||
|
const displayName = user?.user_metadata.full_name
|
||||||
|
const email = user?.email
|
||||||
|
const id = user?.id
|
||||||
|
|
||||||
|
// Get User Preferences
|
||||||
|
const user_plan = user?.user_metadata.plan
|
||||||
|
const user_theme = user?.user_metadata.theme
|
||||||
|
const user_color_scheme = user?.user_metadata.color_scheme
|
||||||
|
const user_beta = user?.user_metadata.beta
|
||||||
|
---
|
||||||
|
|
||||||
|
<Settings Title="Account">
|
||||||
|
<h2>Beta</h2>
|
||||||
|
|
||||||
|
{user_beta ?
|
||||||
|
<QuickFormButton
|
||||||
|
Action="/api/account/preference/beta-off"
|
||||||
|
Method="post"
|
||||||
|
Button="Leave Beta Program"
|
||||||
|
/>
|
||||||
|
:
|
||||||
|
<QuickFormButton
|
||||||
|
Action="/api/account/preference/beta-on"
|
||||||
|
Method="post"
|
||||||
|
Button="Join Beta Program"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
</Settings>
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
#sb-s-beta {
|
||||||
|
background: white;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
function CheckPasswordConfirmation() {
|
||||||
|
const input = document.getElementById('confirm_password');
|
||||||
|
if (input.value !== document.getElementById('password').value) {
|
||||||
|
input.setCustomValidity('Password Must be Matching.');
|
||||||
|
} else {
|
||||||
|
// input is valid -- reset the error message
|
||||||
|
input.setCustomValidity('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,21 +1,6 @@
|
||||||
---
|
---
|
||||||
import Base from "@layouts/Base.astro"
|
import QuickForm from "@components/QuickForm.astro"
|
||||||
|
import Settings from "@layouts/Settings.astro"
|
||||||
// Messages
|
|
||||||
if (Astro.url.href.endsWith('CheckEmail')) {var MessageCheckEmail = true}
|
|
||||||
else {var MessageCheckEmail = false}
|
|
||||||
|
|
||||||
if (Astro.url.href.endsWith('AvatarUpdated')) {var MessageAvatarUpdated = true}
|
|
||||||
else {var MessageAvatarUpdated = false}
|
|
||||||
|
|
||||||
if (Astro.url.href.endsWith('NameUpdated')) {var MessageNameUpdated = true}
|
|
||||||
else {var MessageNameUpdated = false}
|
|
||||||
|
|
||||||
if (Astro.url.href.endsWith('EmailConfirmed')) {var MessageEmailConfirmed = true}
|
|
||||||
else {var MessageEmailConfirmed = false}
|
|
||||||
|
|
||||||
if (Astro.url.href.endsWith('PasswordReset')) {var MessagePasswordReset = true}
|
|
||||||
else {var MessagePasswordReset = false}
|
|
||||||
|
|
||||||
// Supabase Data
|
// Supabase Data
|
||||||
import { supabase } from "@library/supabase"
|
import { supabase } from "@library/supabase"
|
||||||
|
@ -30,101 +15,56 @@ const user_plan = user?.user_metadata.plan
|
||||||
const user_theme = user?.user_metadata.theme
|
const user_theme = user?.user_metadata.theme
|
||||||
const user_color_scheme = user?.user_metadata.color_scheme
|
const user_color_scheme = user?.user_metadata.color_scheme
|
||||||
const user_beta = user?.user_metadata.beta
|
const user_beta = user?.user_metadata.beta
|
||||||
|
|
||||||
// Date - Readable Format (MONTH DAY, YEAR at #:##:## AM/PM / December 9, 2023 at 5:12:43 PM)
|
|
||||||
const dateFormat = { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' }
|
|
||||||
|
|
||||||
/// Created Date
|
|
||||||
const createdDate = new Date(user?.created_at)
|
|
||||||
const createDate = createdDate.toLocaleDateString('en-US', dateFormat)
|
|
||||||
|
|
||||||
/// Last Logged In
|
|
||||||
const lastSignIn = new Date(user?.last_sign_in_at)
|
|
||||||
const lastSignInDate = lastSignIn.toLocaleDateString('en-US', dateFormat)
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<Base Title="Account">
|
<Settings Title="Account">
|
||||||
<!-- Dummy Sidebar -->
|
<div class="account-info-cet">
|
||||||
<div>
|
<div>
|
||||||
<span class="dummies" style="width:80%;"></span>
|
<img src={avatarUrl}/>
|
||||||
<span class="dummies" style="width:80%;"></span>
|
<div style="margin-left: 12px; display: flex;flex-direction: column;text-align: left;float: left;align-items: baseline;">
|
||||||
<span class="dummies" style="width:80%;"></span>
|
<h2>{displayName}</h2>
|
||||||
<span class="dummies" style="width:80%;"></span>
|
<p>{email}</p>
|
||||||
<br/>
|
</div>
|
||||||
<br/>
|
</div>
|
||||||
<br/>
|
<div>
|
||||||
<span class="dummies" style="width:80%;"></span>
|
<p>{user_plan}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<QuickForm
|
||||||
|
Action="/api/account/update-avatar"
|
||||||
|
Method="post"
|
||||||
|
Label="Avatar"
|
||||||
|
Name="avatar"
|
||||||
|
Type="url"
|
||||||
|
Value={avatarUrl}
|
||||||
|
Button="Update"
|
||||||
|
/>
|
||||||
|
<QuickForm
|
||||||
|
Action="/api/account/update-name"
|
||||||
|
Method="post"
|
||||||
|
Label="Display Name"
|
||||||
|
Name="name"
|
||||||
|
Type="text"
|
||||||
|
Value={displayName}
|
||||||
|
Button="Update"
|
||||||
|
/>
|
||||||
|
<QuickForm
|
||||||
|
Action="/api/account/update-email"
|
||||||
|
Method="post"
|
||||||
|
Label="Email"
|
||||||
|
Name="email"
|
||||||
|
Type="email"
|
||||||
|
Value={email}
|
||||||
|
Button="Update"
|
||||||
|
/>
|
||||||
|
</Settings>
|
||||||
|
|
||||||
<!-- Account -->
|
<style is:global>
|
||||||
<div class="dashboard-content">
|
#sb-s-account {
|
||||||
<!-- Messages -->
|
background: white;
|
||||||
{MessageCheckEmail ? <p class="message-in">Check your email</p> : null}
|
color: black;
|
||||||
{MessageAvatarUpdated ? <p class="message-in">Your avatar has been updated</p> : null}
|
}
|
||||||
{MessageNameUpdated ? <p class="message-in">Your display name has been updated</p> : null}
|
</style>
|
||||||
{MessageEmailConfirmed ? <p class="message-in">Email confirmed</p> : null}
|
|
||||||
{MessagePasswordReset ? <p class="message-in">Your new password has been updated</p> : null}
|
|
||||||
<!-- Account Information -->
|
|
||||||
<h2>Your Account</h2>
|
|
||||||
<p>Plan: {user_plan}</p>
|
|
||||||
<p>Display Name: {displayName}</p>
|
|
||||||
<p>Email: <u>{email}</u></p>
|
|
||||||
<hr/>
|
|
||||||
<p>ID: {id}</p>
|
|
||||||
<p>Created at: {createDate}</p>
|
|
||||||
<p>Lasted login: {lastSignInDate}</p>
|
|
||||||
<hr/>
|
|
||||||
<!-- Account Preferences -->
|
|
||||||
<h2>Preferences</h2>
|
|
||||||
<p>Theme: {user_theme}</p>
|
|
||||||
<p>Color Scheme: {user_color_scheme}</p>
|
|
||||||
{user_beta ?
|
|
||||||
<form method="post" action="/api/account/preferences/beta-off"><button type="submit">Leave Beta</button></form>
|
|
||||||
:
|
|
||||||
<form method="post" action="/api/account/preferences/beta-on"><button type="submit">Enter Beta</button></form>
|
|
||||||
}
|
|
||||||
</p>
|
|
||||||
<hr/>
|
|
||||||
<!-- Account Actions -->
|
|
||||||
<form action="/api/account/update-avatar" method="post">
|
|
||||||
<p>Change Avatar</p>
|
|
||||||
<div class="form-field">
|
|
||||||
<label style="font-size: 12px;" for="avatar_url">Avatar URL</label>
|
|
||||||
<input id="avatar_url" type="url" name="avatar_url" value={avatarUrl} required />
|
|
||||||
</div>
|
|
||||||
<button type="submit">Update</button>
|
|
||||||
</form>
|
|
||||||
<form action="/api/account/update-name" method="post">
|
|
||||||
<p>Update Display Name</p>
|
|
||||||
<div class="form-field">
|
|
||||||
<label style="font-size: 12px;" for="name">New Display Name</label>
|
|
||||||
<input id="name" type="text" name="name" value={displayName} required />
|
|
||||||
</div>
|
|
||||||
<button type="submit">Update</button>
|
|
||||||
</form>
|
|
||||||
<form action="/api/account/update-email" method="post">
|
|
||||||
<p>Change Email</p>
|
|
||||||
<div class="form-field">
|
|
||||||
<label style="font-size: 12px;" for="email">New Email</label>
|
|
||||||
<input id="email" type="email" name="email" value={email} required />
|
|
||||||
</div>
|
|
||||||
<button type="submit">Update</button>
|
|
||||||
</form>
|
|
||||||
<form action="/api/account/update-password" method="post">
|
|
||||||
<p>Change Password</p>
|
|
||||||
<div class="form-field">
|
|
||||||
<label style="font-size: 12px;" for="password">New Password</label>
|
|
||||||
<input id="password" type="password" name="password" oninput="CheckPasswordConfirmation()" required />
|
|
||||||
</div>
|
|
||||||
<div class="form-field">
|
|
||||||
<label style="font-size: 12px;" for="confirm_password">Confirm Password</label>
|
|
||||||
<input id="confirm_password" type="password" name="confirm_password" oninput="CheckPasswordConfirmation()" required />
|
|
||||||
</div>
|
|
||||||
<button type="submit">Update</button>
|
|
||||||
</form>
|
|
||||||
<p>Do you want to delete your accout? <form action="/api/account/delete" method="post"><button style="color: rgb(255, 125, 125); text-decoration: none;">Delete account</a>.</button></form>
|
|
||||||
</div>
|
|
||||||
</Base>
|
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
function CheckPasswordConfirmation() {
|
function CheckPasswordConfirmation() {
|
||||||
|
@ -136,11 +76,4 @@ function CheckPasswordConfirmation() {
|
||||||
input.setCustomValidity('');
|
input.setCustomValidity('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style is:inline>
|
|
||||||
.content {
|
|
||||||
display: grid !important;
|
|
||||||
grid-template-columns: 160px auto !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
146
src/pages/account/old.astro
Normal file
146
src/pages/account/old.astro
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
---
|
||||||
|
import Base from "@layouts/Base.astro"
|
||||||
|
|
||||||
|
// Messages
|
||||||
|
if (Astro.url.href.endsWith('CheckEmail')) {var MessageCheckEmail = true}
|
||||||
|
else {var MessageCheckEmail = false}
|
||||||
|
|
||||||
|
if (Astro.url.href.endsWith('AvatarUpdated')) {var MessageAvatarUpdated = true}
|
||||||
|
else {var MessageAvatarUpdated = false}
|
||||||
|
|
||||||
|
if (Astro.url.href.endsWith('NameUpdated')) {var MessageNameUpdated = true}
|
||||||
|
else {var MessageNameUpdated = false}
|
||||||
|
|
||||||
|
if (Astro.url.href.endsWith('EmailConfirmed')) {var MessageEmailConfirmed = true}
|
||||||
|
else {var MessageEmailConfirmed = false}
|
||||||
|
|
||||||
|
if (Astro.url.href.endsWith('PasswordReset')) {var MessagePasswordReset = true}
|
||||||
|
else {var MessagePasswordReset = false}
|
||||||
|
|
||||||
|
// Supabase Data
|
||||||
|
import { supabase } from "@library/supabase"
|
||||||
|
const { data: { user } } = await supabase.auth.getUser()
|
||||||
|
const avatarUrl = user?.user_metadata.avatar_url
|
||||||
|
const displayName = user?.user_metadata.full_name
|
||||||
|
const email = user?.email
|
||||||
|
const id = user?.id
|
||||||
|
|
||||||
|
// Get User Preferences
|
||||||
|
const user_plan = user?.user_metadata.plan
|
||||||
|
const user_theme = user?.user_metadata.theme
|
||||||
|
const user_color_scheme = user?.user_metadata.color_scheme
|
||||||
|
const user_beta = user?.user_metadata.beta
|
||||||
|
|
||||||
|
// Date - Readable Format (MONTH DAY, YEAR at #:##:## AM/PM / December 9, 2023 at 5:12:43 PM)
|
||||||
|
const dateFormat = { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' }
|
||||||
|
|
||||||
|
/// Created Date
|
||||||
|
const createdDate = new Date(user?.created_at)
|
||||||
|
const createDate = createdDate.toLocaleDateString('en-US', dateFormat)
|
||||||
|
|
||||||
|
/// Last Logged In
|
||||||
|
const lastSignIn = new Date(user?.last_sign_in_at)
|
||||||
|
const lastSignInDate = lastSignIn.toLocaleDateString('en-US', dateFormat)
|
||||||
|
---
|
||||||
|
|
||||||
|
<Base Title="Account">
|
||||||
|
<!-- Dummy Sidebar -->
|
||||||
|
<div>
|
||||||
|
<span class="dummies" style="width:80%;"></span>
|
||||||
|
<span class="dummies" style="width:80%;"></span>
|
||||||
|
<span class="dummies" style="width:80%;"></span>
|
||||||
|
<span class="dummies" style="width:80%;"></span>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<span class="dummies" style="width:80%;"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Account -->
|
||||||
|
<div class="dashboard-content">
|
||||||
|
<!-- Messages -->
|
||||||
|
{MessageCheckEmail ? <p class="message-in">Check your email</p> : null}
|
||||||
|
{MessageAvatarUpdated ? <p class="message-in">Your avatar has been updated</p> : null}
|
||||||
|
{MessageNameUpdated ? <p class="message-in">Your display name has been updated</p> : null}
|
||||||
|
{MessageEmailConfirmed ? <p class="message-in">Email confirmed</p> : null}
|
||||||
|
{MessagePasswordReset ? <p class="message-in">Your new password has been updated</p> : null}
|
||||||
|
<!-- Account Information -->
|
||||||
|
<h2>Your Account</h2>
|
||||||
|
<p>Plan: {user_plan}</p>
|
||||||
|
<p>Display Name: {displayName}</p>
|
||||||
|
<p>Email: <u>{email}</u></p>
|
||||||
|
<hr/>
|
||||||
|
<p>ID: {id}</p>
|
||||||
|
<p>Created at: {createDate}</p>
|
||||||
|
<p>Lasted login: {lastSignInDate}</p>
|
||||||
|
<hr/>
|
||||||
|
<!-- Account Preferences -->
|
||||||
|
<h2>Preferences</h2>
|
||||||
|
<p>Theme: {user_theme}</p>
|
||||||
|
<p>Color Scheme: {user_color_scheme}</p>
|
||||||
|
{user_beta ?
|
||||||
|
<form method="post" action="/api/account/preferences/beta-off"><button type="submit">Leave Beta</button></form>
|
||||||
|
:
|
||||||
|
<form method="post" action="/api/account/preferences/beta-on"><button type="submit">Enter Beta</button></form>
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
<hr/>
|
||||||
|
<!-- Account Actions -->
|
||||||
|
<form action="/api/account/update-avatar" method="post">
|
||||||
|
<p>Change Avatar</p>
|
||||||
|
<div class="form-field">
|
||||||
|
<label style="font-size: 12px;" for="avatar_url">Avatar URL</label>
|
||||||
|
<input id="avatar_url" type="url" name="avatar_url" value={avatarUrl} required />
|
||||||
|
</div>
|
||||||
|
<button type="submit">Update</button>
|
||||||
|
</form>
|
||||||
|
<form action="/api/account/update-name" method="post">
|
||||||
|
<p>Update Display Name</p>
|
||||||
|
<div class="form-field">
|
||||||
|
<label style="font-size: 12px;" for="name">New Display Name</label>
|
||||||
|
<input id="name" type="text" name="name" value={displayName} required />
|
||||||
|
</div>
|
||||||
|
<button type="submit">Update</button>
|
||||||
|
</form>
|
||||||
|
<form action="/api/account/update-email" method="post">
|
||||||
|
<p>Change Email</p>
|
||||||
|
<div class="form-field">
|
||||||
|
<label style="font-size: 12px;" for="email">New Email</label>
|
||||||
|
<input id="email" type="email" name="email" value={email} required />
|
||||||
|
</div>
|
||||||
|
<button type="submit">Update</button>
|
||||||
|
</form>
|
||||||
|
<form action="/api/account/update-password" method="post">
|
||||||
|
<p>Change Password</p>
|
||||||
|
<div class="form-field">
|
||||||
|
<label style="font-size: 12px;" for="password">New Password</label>
|
||||||
|
<input id="password" type="password" name="password" oninput="CheckPasswordConfirmation()" required />
|
||||||
|
</div>
|
||||||
|
<div class="form-field">
|
||||||
|
<label style="font-size: 12px;" for="confirm_password">Confirm Password</label>
|
||||||
|
<input id="confirm_password" type="password" name="confirm_password" oninput="CheckPasswordConfirmation()" required />
|
||||||
|
</div>
|
||||||
|
<button type="submit">Update</button>
|
||||||
|
</form>
|
||||||
|
<p>Do you want to delete your accout? <form action="/api/account/delete" method="post"><button style="color: rgb(255, 125, 125); text-decoration: none;">Delete account</a>.</button></form>
|
||||||
|
</div>
|
||||||
|
</Base>
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
function CheckPasswordConfirmation() {
|
||||||
|
const input = document.getElementById('confirm_password');
|
||||||
|
if (input.value !== document.getElementById('password').value) {
|
||||||
|
input.setCustomValidity('Password Must be Matching.');
|
||||||
|
} else {
|
||||||
|
// input is valid -- reset the error message
|
||||||
|
input.setCustomValidity('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style is:inline>
|
||||||
|
.content {
|
||||||
|
display: grid !important;
|
||||||
|
grid-template-columns: 160px auto !important;
|
||||||
|
}
|
||||||
|
</style>
|
74
src/pages/account/preferences.astro
Normal file
74
src/pages/account/preferences.astro
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
---
|
||||||
|
import QuickForm from "@components/QuickForm.astro"
|
||||||
|
import QuickFormButton from "@components/QuickFormButton.astro"
|
||||||
|
import Settings from "@layouts/Settings.astro"
|
||||||
|
|
||||||
|
// Supabase Data
|
||||||
|
import { supabase } from "@library/supabase"
|
||||||
|
const { data: { user } } = await supabase.auth.getUser()
|
||||||
|
const avatarUrl = user?.user_metadata.avatar_url
|
||||||
|
const displayName = user?.user_metadata.full_name
|
||||||
|
const email = user?.email
|
||||||
|
const id = user?.id
|
||||||
|
|
||||||
|
// Get User Preferences
|
||||||
|
const user_plan = user?.user_metadata.plan
|
||||||
|
const user_theme = user?.user_metadata.theme
|
||||||
|
const user_color_scheme = user?.user_metadata.color_scheme
|
||||||
|
const user_beta = user?.user_metadata.beta
|
||||||
|
---
|
||||||
|
|
||||||
|
<Settings Title="Account">
|
||||||
|
<h2>Preferences</h2>
|
||||||
|
|
||||||
|
<p>Theme</p>
|
||||||
|
<p style="font-size: 14px; color: gray;">Current Theme: {user_theme}</p>
|
||||||
|
<QuickFormButton
|
||||||
|
Action="/api/account/preference/theme/light"
|
||||||
|
Method="post"
|
||||||
|
Button="Light"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<QuickFormButton
|
||||||
|
Action="/api/account/preference/theme/dark"
|
||||||
|
Method="post"
|
||||||
|
Button="Dark"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<p>Color Scheme</p>
|
||||||
|
<p style="font-size: 14px; color: gray;">Current Scheme: {user_color_scheme}</p>
|
||||||
|
<QuickFormButton
|
||||||
|
Action="/api/account/preference/color/default"
|
||||||
|
Method="post"
|
||||||
|
Button="Default"
|
||||||
|
/>
|
||||||
|
<QuickFormButton
|
||||||
|
Action="/api/account/preference/color/red"
|
||||||
|
Method="post"
|
||||||
|
Button="Red"
|
||||||
|
/>
|
||||||
|
<QuickFormButton
|
||||||
|
Action="/api/account/preference/color/green"
|
||||||
|
Method="post"
|
||||||
|
Button="Green"
|
||||||
|
/>
|
||||||
|
</Settings>
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
#sb-s-preferences {
|
||||||
|
background: white;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
function CheckPasswordConfirmation() {
|
||||||
|
const input = document.getElementById('confirm_password');
|
||||||
|
if (input.value !== document.getElementById('password').value) {
|
||||||
|
input.setCustomValidity('Password Must be Matching.');
|
||||||
|
} else {
|
||||||
|
// input is valid -- reset the error message
|
||||||
|
input.setCustomValidity('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -14,5 +14,5 @@ export const POST: APIRoute = async ({ redirect }) => {
|
||||||
return new Response(error.message, { status: 500 })
|
return new Response(error.message, { status: 500 })
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect("/account")
|
return redirect("/account/beta")
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,5 +14,5 @@ export const POST: APIRoute = async ({ redirect }) => {
|
||||||
return new Response(error.message, { status: 500 })
|
return new Response(error.message, { status: 500 })
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect("/account")
|
return redirect("/account/beta")
|
||||||
}
|
}
|
||||||
|
|
29
src/pages/api/auth/anon.ts
Normal file
29
src/pages/api/auth/anon.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import type { APIRoute } from "astro"
|
||||||
|
import { supabase } from "@library/supabase"
|
||||||
|
|
||||||
|
export const GET: APIRoute = async ({ cookies, request, redirect }) => {
|
||||||
|
const { error } = await supabase.auth.signInAnonymously({
|
||||||
|
options: {
|
||||||
|
data: {
|
||||||
|
full_name: 'Anonymous',
|
||||||
|
avatar_url: 'https://img.sudovanilla.org/MAuSBXN.png',
|
||||||
|
plan: "Free",
|
||||||
|
theme: "Dark",
|
||||||
|
color_scheme: "Purple",
|
||||||
|
beta: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return new Response(error.message, { status: 500 })
|
||||||
|
}
|
||||||
|
|
||||||
|
cookies.set("anonymous-session", 'true', {
|
||||||
|
path: "/",
|
||||||
|
secure: true,
|
||||||
|
httpOnly: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
return redirect("/?=anonymous")
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
import type { APIRoute } from "astro"
|
import type { APIRoute } from "astro"
|
||||||
|
import { supabase } from "@library/supabase"
|
||||||
|
import type { Provider } from "@supabase/supabase-js"
|
||||||
|
|
||||||
export const GET: APIRoute = async ({ cookies, redirect }) => {
|
export const GET: APIRoute = async ({ cookies, redirect }) => {
|
||||||
cookies.delete("sb-access-token", { path: "/" })
|
cookies.delete("sb-access-token", { path: "/" })
|
||||||
cookies.delete("sb-refresh-token", { path: "/" })
|
cookies.delete("sb-refresh-token", { path: "/" })
|
||||||
|
const { error } = await supabase.auth.signOut()
|
||||||
return redirect("/signin")
|
return redirect("/signin")
|
||||||
}
|
}
|
|
@ -46,10 +46,21 @@ console.log(subs)
|
||||||
<hr/>
|
<hr/>
|
||||||
<h3>Channels</h3>
|
<h3>Channels</h3>
|
||||||
{channels.map((channel) =>
|
{channels.map((channel) =>
|
||||||
<a href={'/creator/' + channel.id}>{channel.creator}</a>
|
<a class="creator-list" href={'/creator/' + channel.id}>{channel.creator}</a>
|
||||||
)}
|
)}
|
||||||
<hr/>
|
<hr/>
|
||||||
{subs.map((data) =>
|
{subs.map((data) =>
|
||||||
<p><a href={'/creator/' + data.Id}>{data.Id}</a> | <a href={'/api/account/remove?=' + data.Id}>Unsubscribe</a></p>
|
<p><a href={'/creator/' + data.Id}>{data.Id}</a> | <a href={'/api/account/remove?=' + data.Id}>Unsubscribe</a></p>
|
||||||
)}
|
)}
|
||||||
</Base>
|
</Base>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.creator-list {
|
||||||
|
background: #464646;
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -5,7 +5,7 @@ import Base from "@layouts/Base.astro"
|
||||||
<Base Title="Supabase - Register">
|
<Base Title="Supabase - Register">
|
||||||
<h2>Register for Supabase Demo</h2>
|
<h2>Register for Supabase Demo</h2>
|
||||||
<p>Already have an account? <a href="/signin">Sign In</a>.</p>
|
<p>Already have an account? <a href="/signin">Sign In</a>.</p>
|
||||||
<form action="/api/auth/register" method="post">
|
<form action="/api/auth/register" method="post" onsubmit="LoginTriggered()">
|
||||||
<div class="form-field">
|
<div class="form-field">
|
||||||
<label for="name">Avatar URL</label>
|
<label for="name">Avatar URL</label>
|
||||||
<input id="avatar_url" type="url" name="avatar_url" placeholder="https://example.com/profile.png" />
|
<input id="avatar_url" type="url" name="avatar_url" placeholder="https://example.com/profile.png" />
|
||||||
|
@ -22,18 +22,25 @@ import Base from "@layouts/Base.astro"
|
||||||
<label for="password">Password</label>
|
<label for="password">Password</label>
|
||||||
<input id="password" type="password" name="password" />
|
<input id="password" type="password" name="password" />
|
||||||
</div>
|
</div>
|
||||||
<button type="submit">Register</button>
|
<button onclick="LoginTriggered()" style="float: right;" type="submit">Register</button>
|
||||||
</form>
|
</form>
|
||||||
<hr/>
|
<form action="/api/auth/anon" method="get"><button style="border-color: gray;" type="submit">Create Anomyous Session</button></form>
|
||||||
<p>
|
<br/>
|
||||||
<span>Or with</span>
|
<br/>
|
||||||
</p>
|
<center><span>Or with</span></center>
|
||||||
|
<br/>
|
||||||
<form action="/api/auth/signin" method="post">
|
<form action="/api/auth/signin" method="post">
|
||||||
<div class="oauth-grid">
|
<div class="oauth-grid">
|
||||||
<button value="github" name="provider" type="submit">Sign Up with GitHub</button>
|
<button value="github" name="provider" type="submit">Sign Up with GitHub</button>
|
||||||
<button value="gitlab" name="provider" type="submit">Sign Up with GitLab</button>
|
|
||||||
<button value="spotify" name="provider" type="submit">Sign Up with Spotify</button>
|
|
||||||
<button value="discord" name="provider" type="submit">Sign Up with Discord</button>
|
<button value="discord" name="provider" type="submit">Sign Up with Discord</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Base>
|
</Base>
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
function LoginTriggered() {
|
||||||
|
document.querySelector("body > div > form > button").innerText = 'Loading, please wait...'
|
||||||
|
document.querySelector(".pri-submit").style.filter = "brightness(0.5)"
|
||||||
|
document.querySelector(".pri-submit").style.cursor = "wait"
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -5,7 +5,7 @@ import Base from "@layouts/Base.astro"
|
||||||
<Base Title="Supabase - Sign In">
|
<Base Title="Supabase - Sign In">
|
||||||
<h2>Sign In</h2>
|
<h2>Sign In</h2>
|
||||||
<p>Don't have an account? <a href="/register">Sign Up</a>.</p>
|
<p>Don't have an account? <a href="/register">Sign Up</a>.</p>
|
||||||
<form action="/api/auth/signin" method="post">
|
<form action="/api/auth/signin" method="post" onsubmit="LoginTriggered()">
|
||||||
<div class="form-field">
|
<div class="form-field">
|
||||||
<label for="email">Email</label>
|
<label for="email">Email</label>
|
||||||
<input id="email" type="email" name="email" />
|
<input id="email" type="email" name="email" />
|
||||||
|
@ -14,11 +14,12 @@ import Base from "@layouts/Base.astro"
|
||||||
<label for="password">Password</label>
|
<label for="password">Password</label>
|
||||||
<input id="password" type="password" name="password" />
|
<input id="password" type="password" name="password" />
|
||||||
</div>
|
</div>
|
||||||
<button type="submit">Sign In</button>
|
<button onclick="LoginTriggered()" class="pri-submit" style="float: right;" type="submit">Sign In</button>
|
||||||
<hr />
|
<br/>
|
||||||
<p>
|
<br/>
|
||||||
<span>Or with</span>
|
<br/>
|
||||||
</p>
|
<center><span>Or with</span></center>
|
||||||
|
<br/>
|
||||||
<form action="/api/auth/signin" method="post">
|
<form action="/api/auth/signin" method="post">
|
||||||
<div class="oauth-grid">
|
<div class="oauth-grid">
|
||||||
<button value="github" name="provider" type="submit">Sign In with GitHub</button>
|
<button value="github" name="provider" type="submit">Sign In with GitHub</button>
|
||||||
|
@ -29,3 +30,11 @@ import Base from "@layouts/Base.astro"
|
||||||
</form>
|
</form>
|
||||||
</form>
|
</form>
|
||||||
</Base>
|
</Base>
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
function LoginTriggered() {
|
||||||
|
document.querySelector("body > div > form > button").innerText = 'Loading, please wait...'
|
||||||
|
document.querySelector(".pri-submit").style.filter = "brightness(0.5)"
|
||||||
|
document.querySelector(".pri-submit").style.cursor = "wait"
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,5 +1,5 @@
|
||||||
body {
|
body {
|
||||||
background: #1c1c1c;
|
background: black;
|
||||||
color: #fdfdfd;
|
color: #fdfdfd;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
@ -17,13 +17,13 @@ a {
|
||||||
|
|
||||||
button {
|
button {
|
||||||
color: color;
|
color: color;
|
||||||
color: white;
|
color: black;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
background: #cbddbe5e;
|
background: white;
|
||||||
padding: 6px;
|
padding: 6px 12px;
|
||||||
border-radius: 4px;
|
border-radius: 3rem;
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -32,43 +32,39 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
background: #232323;
|
|
||||||
border: 1px #2e2e2e solid;
|
|
||||||
transition: 1.3s border;
|
|
||||||
border-radius: 6px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px;
|
padding: 6px 0px;
|
||||||
margin-top: 24px;
|
margin-top: 12px;
|
||||||
&:hover {
|
|
||||||
border-color: #3ecf8e;
|
|
||||||
transition: 1.3s border;
|
|
||||||
}
|
|
||||||
h2 {
|
h2 {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
.header-start {
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
.header-end {
|
.header-end {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
a {
|
a {
|
||||||
color: color;
|
color: black;
|
||||||
color: white;
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
background: #cbddbe5e;
|
background: white;
|
||||||
padding: 6px;
|
padding: 6px 12px;
|
||||||
border-radius: 4px;
|
border-radius: 3rem;
|
||||||
&:hover {
|
&:hover {
|
||||||
filter: brightness(0.8)
|
filter: brightness(0.8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
img {
|
img {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
border-radius: 6px;
|
border-radius: 3rem;
|
||||||
border: 2px #2e2e2e solid;
|
border: 2px #282828 solid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,10 +88,6 @@ header {
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
background: #232323;
|
|
||||||
border: 1px #2e2e2e solid;
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 12px;
|
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,11 +113,11 @@ header {
|
||||||
grid-auto-flow: column;
|
grid-auto-flow: column;
|
||||||
grid-gap: 6px;
|
grid-gap: 6px;
|
||||||
button {
|
button {
|
||||||
background: #494949;
|
background: transparent;
|
||||||
border: none;
|
border: 1px white solid;
|
||||||
color: white;
|
color: white;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
border-radius: 6px;
|
border-radius: 3rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
filter: brightness(0.8)
|
filter: brightness(0.8)
|
||||||
|
|
Loading…
Reference in a new issue