changed "Online Store" to "Dashboard"
This commit is contained in:
parent
7af88c424d
commit
43fe443c52
6 changed files with 111 additions and 167 deletions
|
@ -1,85 +1,92 @@
|
||||||
import PocketBase from "pocketbase";
|
import PocketBase from "pocketbase";
|
||||||
|
|
||||||
export class RedirectHandler {
|
export class RedirectHandler {
|
||||||
private pb: PocketBase;
|
private pb: PocketBase;
|
||||||
private contentEl: HTMLElement;
|
private contentEl: HTMLElement;
|
||||||
private params: URLSearchParams;
|
private params: URLSearchParams;
|
||||||
private provider: any;
|
private provider: any;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.pb = new PocketBase("https://pocketbase.ieeeucsd.org");
|
this.pb = new PocketBase("https://pocketbase.ieeeucsd.org");
|
||||||
this.contentEl = this.getContentElement();
|
this.contentEl = this.getContentElement();
|
||||||
this.params = new URLSearchParams(window.location.search);
|
this.params = new URLSearchParams(window.location.search);
|
||||||
this.provider = this.getStoredProvider();
|
this.provider = this.getStoredProvider();
|
||||||
this.handleRedirect();
|
this.handleRedirect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private getContentElement(): HTMLElement {
|
||||||
|
const contentEl = document.getElementById("content");
|
||||||
|
if (!contentEl) {
|
||||||
|
throw new Error("Content element not found");
|
||||||
|
}
|
||||||
|
return contentEl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getStoredProvider() {
|
||||||
|
return JSON.parse(localStorage.getItem("provider") || "{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private showError(message: string) {
|
||||||
|
this.contentEl.innerHTML = `
|
||||||
|
<p class='text-red-500 text-2xl font-medium mb-4'>${message}</p>
|
||||||
|
<a href="/" class="btn btn-primary">
|
||||||
|
Return to Home
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleRedirect() {
|
||||||
|
const code = this.params.get("code");
|
||||||
|
const state = this.params.get("state");
|
||||||
|
|
||||||
|
if (!code) {
|
||||||
|
this.showError("No authorization code found in URL.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getContentElement(): HTMLElement {
|
if (state !== this.provider.state) {
|
||||||
const contentEl = document.getElementById("content");
|
this.showError("Invalid state parameter.");
|
||||||
if (!contentEl) {
|
return;
|
||||||
throw new Error("Content element not found");
|
|
||||||
}
|
|
||||||
return contentEl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getStoredProvider() {
|
try {
|
||||||
return JSON.parse(localStorage.getItem("provider") || "{}");
|
const authData = await this.pb
|
||||||
}
|
.collection("users")
|
||||||
|
.authWithOAuth2Code(
|
||||||
|
"oidc",
|
||||||
|
code,
|
||||||
|
this.provider.codeVerifier,
|
||||||
|
window.location.origin + "/oauth2-redirect",
|
||||||
|
{ emailVisibility: false },
|
||||||
|
);
|
||||||
|
|
||||||
private showError(message: string) {
|
console.log("Auth successful:", authData);
|
||||||
this.contentEl.innerHTML = `<p class='text-red-500'>${message}</p>`;
|
this.contentEl.innerHTML = `
|
||||||
}
|
|
||||||
|
|
||||||
private async handleRedirect() {
|
|
||||||
const code = this.params.get("code");
|
|
||||||
const state = this.params.get("state");
|
|
||||||
|
|
||||||
if (!code) {
|
|
||||||
this.showError("No authorization code found in URL.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state !== this.provider.state) {
|
|
||||||
this.showError("Invalid state parameter.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const authData = await this.pb.collection("users").authWithOAuth2Code(
|
|
||||||
"oidc",
|
|
||||||
code,
|
|
||||||
this.provider.codeVerifier,
|
|
||||||
window.location.origin + "/oauth2-redirect",
|
|
||||||
{ emailVisibility: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log("Auth successful:", authData);
|
|
||||||
this.contentEl.innerHTML = `
|
|
||||||
<p class="text-3xl font-bold text-green-500 mb-4">Authentication Successful!</p>
|
<p class="text-3xl font-bold text-green-500 mb-4">Authentication Successful!</p>
|
||||||
<p class="text-2xl font-medium">Redirecting to store...</p>
|
<p class="text-2xl font-medium">Redirecting to store...</p>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<div class="loading loading-spinner loading-lg"></div>
|
<div class="loading loading-spinner loading-lg"></div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Update last login before redirecting
|
// Update last login before redirecting
|
||||||
await this.pb.collection("users").update(authData.record.id, {
|
await this.pb.collection("users").update(authData.record.id, {
|
||||||
last_login: new Date().toISOString()
|
last_login: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clean up and redirect
|
// Clean up and redirect
|
||||||
localStorage.removeItem("provider");
|
localStorage.removeItem("provider");
|
||||||
window.location.href = "/online-store";
|
window.location.href = "/dashboard";
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to update last login:", err);
|
console.error("Failed to update last login:", err);
|
||||||
// Still redirect even if last_login update fails
|
// Still redirect even if last_login update fails
|
||||||
localStorage.removeItem("provider");
|
localStorage.removeItem("provider");
|
||||||
window.location.href = "/online-store";
|
window.location.href = "/dashboard";
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("Auth error:", err);
|
console.error("Auth error:", err);
|
||||||
this.showError(`Failed to complete authentication: ${err.message}`);
|
this.showError(`Failed to complete authentication: ${err.message}`);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ import pages from "../../data/pages.json";
|
||||||
href={page.path}
|
href={page.path}
|
||||||
class={`uppercase rounded-full duration-300 px-[1.5vw] py-[0.2vw] text-[1.2vw] text-nowrap
|
class={`uppercase rounded-full duration-300 px-[1.5vw] py-[0.2vw] text-[1.2vw] text-nowrap
|
||||||
${
|
${
|
||||||
page.name === "Online Store"
|
page.name === "Dashboard"
|
||||||
? "bg-ieee-yellow text-black hover:opacity-70"
|
? "bg-ieee-yellow text-black hover:opacity-70"
|
||||||
: "text-white border-white hover:opacity-50 border-[0.1vw] font-light"
|
: "text-white border-white hover:opacity-50 border-[0.1vw] font-light"
|
||||||
}`}
|
}`}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
<div id="storeItemsGrid" class="h-full">
|
|
||||||
<div
|
|
||||||
class="card bg-base-200 shadow-xl h-full flex items-center justify-center min-h-[400px]"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="card-body flex flex-col items-center justify-center h-full w-full max-w-2xl mx-auto"
|
|
||||||
>
|
|
||||||
<div class="text-center w-full">
|
|
||||||
<h2 class="card-title text-3xl justify-center mb-6">
|
|
||||||
Store Coming Soon!
|
|
||||||
</h2>
|
|
||||||
<div class="space-y-4">
|
|
||||||
<p class="text-base-content/70 text-lg">
|
|
||||||
Our store is currently under development. Check back
|
|
||||||
later for IEEE UCSD merchandise! In the meantime, please
|
|
||||||
make sure your profile is up to date with your IEEE
|
|
||||||
Member ID and resume.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,37 +0,0 @@
|
||||||
---
|
|
||||||
interface Props {
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
price: number;
|
|
||||||
imageUrl: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
price,
|
|
||||||
imageUrl = "https://placehold.co/400x300",
|
|
||||||
} = Astro.props;
|
|
||||||
---
|
|
||||||
|
|
||||||
<div class="card bg-base-200 shadow-xl">
|
|
||||||
<figure class="px-6 pt-6">
|
|
||||||
<div class="relative w-full">
|
|
||||||
<div class="skeleton w-full aspect-[4/3] rounded-xl"></div>
|
|
||||||
<img
|
|
||||||
src={imageUrl}
|
|
||||||
alt={name}
|
|
||||||
class="rounded-xl absolute inset-0 w-full h-full object-cover opacity-0 transition-opacity duration-300"
|
|
||||||
onload="this.classList.remove('opacity-0')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</figure>
|
|
||||||
<div class="card-body">
|
|
||||||
<h2 class="card-title">{name}</h2>
|
|
||||||
<p>{description}</p>
|
|
||||||
<div class="card-actions justify-between items-center mt-2">
|
|
||||||
<span class="text-xl font-semibold">${price.toFixed(2)}</span>
|
|
||||||
<button class="btn btn-primary">Add to Cart</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,26 +1,26 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "Join",
|
"name": "Join",
|
||||||
"path": "/join"
|
"path": "/join"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Events",
|
"name": "Events",
|
||||||
"path": "/events"
|
"path": "/events"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Projects",
|
"name": "Projects",
|
||||||
"path": "/projects"
|
"path": "/projects"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Board",
|
"name": "Board",
|
||||||
"path": "/board"
|
"path": "/board"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Find Us",
|
"name": "Find Us",
|
||||||
"path": "/find"
|
"path": "/find"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Online Store",
|
"name": "Dashboard",
|
||||||
"path": "/online-store"
|
"path": "/dashboard"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,18 +3,15 @@ import Layout from "../layouts/Layout.astro";
|
||||||
const title = "Authenticating...";
|
const title = "Authenticating...";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout {title}>
|
<main class="min-h-screen flex items-center justify-center">
|
||||||
<main class="min-h-screen flex items-center justify-center">
|
<div id="content" class="text-center">
|
||||||
<div id="content" class="text-center">
|
<p class="text-2xl font-medium">Redirecting to dashboard...</p>
|
||||||
<p class="text-2xl font-medium">Redirecting to store...</p>
|
<div class="mt-4">
|
||||||
<div class="mt-4">
|
<div class="loading loading-spinner loading-lg"></div>
|
||||||
<div class="loading loading-spinner loading-lg"></div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
|
||||||
</Layout>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { RedirectHandler } from "../components/auth/RedirectHandler";
|
import { RedirectHandler } from "../components/auth/RedirectHandler";
|
||||||
new RedirectHandler();
|
new RedirectHandler();
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in a new issue