Update pages and UI
This commit is contained in:
parent
da8882b162
commit
087ab36bb0
9 changed files with 371 additions and 63 deletions
9
src/components/Head.astro
Normal file
9
src/components/Head.astro
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
const { Title } = Astro.props
|
||||||
|
---
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=2.2" />
|
||||||
|
<title>{Title}</title>
|
||||||
|
</head>
|
35
src/components/Header.astro
Normal file
35
src/components/Header.astro
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
if (Astro.cookies.get('sb-access-token') && Astro.cookies.get('sb-refresh-token')) {
|
||||||
|
var IsLoggedIn = true
|
||||||
|
} else {
|
||||||
|
var IsLoggedIn = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supabase Data
|
||||||
|
import { supabase } from "../library/supabase"
|
||||||
|
const { data: { user } } = await supabase.auth.getUser()
|
||||||
|
const avatar = user?.user_metadata.avatar_url
|
||||||
|
const beta = user?.user_metadata.beta
|
||||||
|
---
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<div class="header-start">
|
||||||
|
<h2><a href="/">Supabase Demo</a> {beta ? <span>Beta</span> : null}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="header-end">
|
||||||
|
{IsLoggedIn
|
||||||
|
?
|
||||||
|
<img src={avatar}/>
|
||||||
|
<a href="/account">Account</a>
|
||||||
|
<a href="/api/auth/signout">Sign Out</a>
|
||||||
|
:
|
||||||
|
<a href="/register">Register</a>
|
||||||
|
<a href="/signin">Sign in</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
|
||||||
|
</script>
|
16
src/layouts/Base.astro
Normal file
16
src/layouts/Base.astro
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
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 class="content">
|
||||||
|
<slot/>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,45 +1,146 @@
|
||||||
---
|
---
|
||||||
const { user, users } = Astro.locals
|
import Base from "@layouts/Base.astro"
|
||||||
if (!user) {return Astro.redirect("/signin")}
|
|
||||||
import { SESSION_COOKIE, createAdminClient } from "../server/appwrite";
|
|
||||||
|
|
||||||
if (user.emailVerification) {var EmailIsVerified = true}
|
// Messages
|
||||||
else {var EmailIsVerified = false}
|
if (Astro.url.href.endsWith('CheckEmail')) {var MessageCheckEmail = true}
|
||||||
|
else {var MessageCheckEmail = false}
|
||||||
|
|
||||||
if (Astro.cookies.get('anonymous')) {var AN = true}
|
if (Astro.url.href.endsWith('AvatarUpdated')) {var MessageAvatarUpdated = true}
|
||||||
else {var AN = false}
|
else {var MessageAvatarUpdated = false}
|
||||||
|
|
||||||
const { account } = createAdminClient();
|
if (Astro.url.href.endsWith('NameUpdated')) {var MessageNameUpdated = true}
|
||||||
// const session = await account.createMagicURLToken(user.$id,user.email);
|
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)
|
||||||
---
|
---
|
||||||
|
|
||||||
<p>Email: {AN ? <span>None</span> : <span>{user.email}</span>} <span><button><a style="color: white; text-decoration: none;" href="/settings/update-username">Change</a></button></span></p>
|
<Base Title="Account">
|
||||||
<p>ID: {user.$id}</p>
|
<!-- Dummy Sidebar -->
|
||||||
<!-- <p>Phone: {user.phone}</p> -->
|
<div>
|
||||||
<p>Name: {AN ? <span>Anonymous</span> : <span>{user.name}</span>} <span><button><a style="color: white; text-decoration: none;" href="/settings/update-username">Change</a></button></span></p>
|
<span class="dummies" style="width:80%;"></span>
|
||||||
<p>Created at: {user.$createdAt}</p>
|
<span class="dummies" style="width:80%;"></span>
|
||||||
<p>Last login: {user.accessedAt}</p>
|
<span class="dummies" style="width:80%;"></span>
|
||||||
<p>Last updated: {user.$updatedAt}</p>
|
<span class="dummies" style="width:80%;"></span>
|
||||||
<p>Labels:
|
<br/>
|
||||||
{user.labels.map((data) =>
|
<br/>
|
||||||
<ul>
|
<br/>
|
||||||
<li>{data}</li>
|
<span class="dummies" style="width:80%;"></span>
|
||||||
</ul>
|
</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/beta-off"><button type="submit">Leave Beta</button></form>
|
||||||
|
:
|
||||||
|
<form method="post" action="/api/account/beta-on"><button type="submit">Enter Beta</button></form>
|
||||||
|
}
|
||||||
</p>
|
</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>
|
||||||
|
|
||||||
Theme: {user.prefs.darkTheme}
|
<script is:inline>
|
||||||
|
function CheckPasswordConfirmation() {
|
||||||
{EmailIsVerified ?
|
const input = document.getElementById('confirm_password');
|
||||||
<p>Your account is verified</p>
|
if (input.value !== document.getElementById('password').value) {
|
||||||
:
|
input.setCustomValidity('Password Must be Matching.');
|
||||||
<p style="color: rgb(255, 113, 113)">Your account is not verified<!-- [<a href="/api/email/send-verification">Send Verification Email</a>] --></p>
|
} else {
|
||||||
|
// input is valid -- reset the error message
|
||||||
|
input.setCustomValidity('');
|
||||||
}
|
}
|
||||||
|
|
||||||
{AN ?
|
|
||||||
<p>This is an anonmyous account.</p>
|
|
||||||
:
|
|
||||||
<p style="color: rgb(255, 113, 113)">Not an anonmyous account.</p>
|
|
||||||
}
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<a href="/signout">Sign Out</a>
|
<style is:inline>
|
||||||
|
.content {
|
||||||
|
display: grid !important;
|
||||||
|
grid-template-columns: 160px auto !important;
|
||||||
|
}
|
||||||
|
</style>
|
26
src/pages/creator/C6nSFpj9HTCZ5t-N3Rm3-HA.astro
Normal file
26
src/pages/creator/C6nSFpj9HTCZ5t-N3Rm3-HA.astro
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
import Base from "@layouts/Base.astro"
|
||||||
|
const CreatorId = Astro.url.href.split("creator/").pop()
|
||||||
|
import { supabase } from "@library/supabase"
|
||||||
|
const { data: { user } } = await supabase.auth.getUser()
|
||||||
|
const id = user?.id
|
||||||
|
|
||||||
|
let { data: subs } = await supabase
|
||||||
|
.from('subs')
|
||||||
|
.select("*")
|
||||||
|
.eq('UserSubscribed', id)
|
||||||
|
.eq('Id', CreatorId)
|
||||||
|
---
|
||||||
|
|
||||||
|
<Base Title="Supabase Demo">
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||||
|
<p style="font-size: 18px; font-weight: bold;">Vsause</p>
|
||||||
|
<div>
|
||||||
|
{subs[0].Subscribed ?
|
||||||
|
<a style="font-size: 14px;" href={"/api/account/remove?=" + 'C6nSFpj9HTCZ5t-N3Rm3-HA'}>Unsubscribe</a>
|
||||||
|
:
|
||||||
|
<a style="font-size: 14px;" href={"/api/account/add?=" + 'C6nSFpj9HTCZ5t-N3Rm3-HA'}>Subscribe</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Base>
|
|
@ -1,8 +1,55 @@
|
||||||
---
|
---
|
||||||
const { user } = Astro.locals;
|
import Base from "@layouts/Base.astro"
|
||||||
if (user) {
|
|
||||||
return Astro.redirect("/account");
|
// Check Cookies
|
||||||
|
if (Astro.cookies.get('sb-access-token') && Astro.cookies.get('sb-refresh-token')) {
|
||||||
|
var IsLoggedIn = true
|
||||||
|
} else {
|
||||||
|
var IsLoggedIn = false
|
||||||
}
|
}
|
||||||
|
|
||||||
return Astro.redirect("/signin");
|
// Supabase Data
|
||||||
|
import { supabase } from "../library/supabase"
|
||||||
|
const { data: { user } } = await supabase.auth.getUser()
|
||||||
|
const avatar = user?.user_metadata.avatar_url
|
||||||
|
const displayName = user?.user_metadata.full_name
|
||||||
|
const id = user?.id
|
||||||
|
|
||||||
|
// Get Channels
|
||||||
|
const { data: channels, error } = await supabase
|
||||||
|
.from('channels')
|
||||||
|
.select('*')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let { data: subs } = await supabase
|
||||||
|
.from('subs')
|
||||||
|
.select("*")
|
||||||
|
.eq('UserSubscribed', id)
|
||||||
|
|
||||||
|
|
||||||
|
console.log(subs)
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<Base Title="Supabase Demo">
|
||||||
|
{IsLoggedIn
|
||||||
|
?
|
||||||
|
<div class="welcome">
|
||||||
|
<img src={avatar}/>
|
||||||
|
<h2>Welcome back, {displayName}</h2>
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
<div class="welcome">
|
||||||
|
<h2>Welcome!</h2>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<hr/>
|
||||||
|
<h3>Channels</h3>
|
||||||
|
{channels.map((channel) =>
|
||||||
|
<a href={'/creator/' + channel.id}>{channel.creator}</a>
|
||||||
|
)}
|
||||||
|
<hr/>
|
||||||
|
{subs.map((data) =>
|
||||||
|
<p><a href={'/creator/' + data.Id}>{data.Id}</a> | <a href={'/api/account/remove?=' + data.Id}>Unsubscribe</a></p>
|
||||||
|
)}
|
||||||
|
</Base>
|
39
src/pages/register.astro
Normal file
39
src/pages/register.astro
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
import Base from "@layouts/Base.astro"
|
||||||
|
---
|
||||||
|
|
||||||
|
<Base Title="Supabase - Register">
|
||||||
|
<h2>Register for Supabase Demo</h2>
|
||||||
|
<p>Already have an account? <a href="/signin">Sign In</a>.</p>
|
||||||
|
<form action="/api/auth/register" method="post">
|
||||||
|
<div class="form-field">
|
||||||
|
<label for="name">Avatar URL</label>
|
||||||
|
<input id="avatar_url" type="url" name="avatar_url" placeholder="https://example.com/profile.png" />
|
||||||
|
</div>
|
||||||
|
<div class="form-field">
|
||||||
|
<label for="name">Name</label>
|
||||||
|
<input id="name" type="text" name="name" placeholder="John Smith" />
|
||||||
|
</div>
|
||||||
|
<div class="form-field">
|
||||||
|
<label for="email">Email</label>
|
||||||
|
<input id="email" type="email" name="email" placeholder="john@example.com" />
|
||||||
|
</div>
|
||||||
|
<div class="form-field">
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input id="password" type="password" name="password" />
|
||||||
|
</div>
|
||||||
|
<button type="submit">Register</button>
|
||||||
|
</form>
|
||||||
|
<hr/>
|
||||||
|
<p>
|
||||||
|
<span>Or with</span>
|
||||||
|
</p>
|
||||||
|
<form action="/api/auth/signin" method="post">
|
||||||
|
<div class="oauth-grid">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Base>
|
32
src/pages/reset-password.astro
Normal file
32
src/pages/reset-password.astro
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
import Base from "@layouts/Base.astro"
|
||||||
|
---
|
||||||
|
|
||||||
|
<Base Title="Account">
|
||||||
|
<div class="content">
|
||||||
|
<form action="/api/account/reset-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>
|
||||||
|
</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>
|
|
@ -1,28 +1,31 @@
|
||||||
---
|
---
|
||||||
import SignInUp from "../layouts/SignInUp.astro";
|
import Base from "@layouts/Base.astro"
|
||||||
|
|
||||||
import { ID } from "node-appwrite";
|
|
||||||
import { SESSION_COOKIE, createAdminClient } from "../server/appwrite";
|
|
||||||
|
|
||||||
if (Astro.request.method === "POST") {
|
|
||||||
const data = await Astro.request.formData();
|
|
||||||
|
|
||||||
const email = data.get("email") as string;
|
|
||||||
const password = data.get("password") as string;
|
|
||||||
|
|
||||||
const { account } = createAdminClient();
|
|
||||||
const session = await account.createEmailPasswordSession(email, password);
|
|
||||||
|
|
||||||
Astro.cookies.set(SESSION_COOKIE, session.secret, {
|
|
||||||
path: "/",
|
|
||||||
expires: new Date(session.expire),
|
|
||||||
sameSite: "strict",
|
|
||||||
secure: true,
|
|
||||||
httpOnly: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
return Astro.redirect("/account");
|
|
||||||
}
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<SignInUp Title="Demo Login" Type="SignIn"/>
|
<Base Title="Supabase - Sign In">
|
||||||
|
<h2>Sign In</h2>
|
||||||
|
<p>Don't have an account? <a href="/register">Sign Up</a>.</p>
|
||||||
|
<form action="/api/auth/signin" method="post">
|
||||||
|
<div class="form-field">
|
||||||
|
<label for="email">Email</label>
|
||||||
|
<input id="email" type="email" name="email" />
|
||||||
|
</div>
|
||||||
|
<div class="form-field">
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input id="password" type="password" name="password" />
|
||||||
|
</div>
|
||||||
|
<button type="submit">Sign In</button>
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<span>Or with</span>
|
||||||
|
</p>
|
||||||
|
<form action="/api/auth/signin" method="post">
|
||||||
|
<div class="oauth-grid">
|
||||||
|
<button value="github" name="provider" type="submit">Sign In with GitHub</button>
|
||||||
|
<button value="gitlab" name="provider" type="submit">Sign In with GitLab</button>
|
||||||
|
<button value="spotify" name="provider" type="submit">Sign In with Spotify</button>
|
||||||
|
<button value="discord" name="provider" type="submit">Sign In with Discord</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</form>
|
||||||
|
</Base>
|
||||||
|
|
Loading…
Reference in a new issue