From c1749d74b039cb0e4d46512d82c4d3bb275e6811 Mon Sep 17 00:00:00 2001
From: "Builder.io"
Date: Tue, 14 Oct 2025 07:17:34 +0000
Subject: [PATCH] Prettier format pending files
---
.../components/admin/AdminChangelogDigest.tsx | 25 +-
.../components/admin/AdminStatusOverview.tsx | 28 +-
client/components/blog/BlogCategoryChips.tsx | 6 +-
client/components/blog/BlogHero.tsx | 23 +-
.../components/blog/BlogNewsletterSection.tsx | 16 +-
client/components/blog/BlogPostGrid.tsx | 35 +-
client/components/blog/BlogTrendingRail.tsx | 12 +-
.../notifications/NotificationBell.tsx | 34 +-
client/contexts/AuthContext.tsx | 4 +-
client/pages/Admin.tsx | 7 +-
client/pages/Blog.tsx | 92 +++--
client/pages/Changelog.tsx | 369 +++++++++++-------
client/pages/Login.tsx | 15 +-
server/email.ts | 10 +-
14 files changed, 467 insertions(+), 209 deletions(-)
diff --git a/client/components/admin/AdminChangelogDigest.tsx b/client/components/admin/AdminChangelogDigest.tsx
index 1315ba1d..315aab9d 100644
--- a/client/components/admin/AdminChangelogDigest.tsx
+++ b/client/components/admin/AdminChangelogDigest.tsx
@@ -1,4 +1,10 @@
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { formatDistanceToNow } from "date-fns";
@@ -84,8 +90,13 @@ export default function AdminChangelogDigest({
Version {entry.version} • {entry.author}
-
- {formatDistanceToNow(new Date(entry.date), { addSuffix: true })}
+
+ {formatDistanceToNow(new Date(entry.date), {
+ addSuffix: true,
+ })}
@@ -100,10 +111,14 @@ export default function AdminChangelogDigest({
key={`${entry.id}-change-${idx}`}
className="flex items-start gap-2"
>
-
+
- {change.type.charAt(0).toUpperCase() + change.type.slice(1)}:
+ {change.type.charAt(0).toUpperCase() +
+ change.type.slice(1)}
+ :
{" "}
{change.description}
diff --git a/client/components/admin/AdminStatusOverview.tsx b/client/components/admin/AdminStatusOverview.tsx
index a846fbc4..7ed8f604 100644
--- a/client/components/admin/AdminStatusOverview.tsx
+++ b/client/components/admin/AdminStatusOverview.tsx
@@ -1,4 +1,10 @@
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import type { LucideIcon } from "lucide-react";
@@ -25,8 +31,7 @@ interface AdminStatusOverviewProps {
}
const statusBadgeClass: Record = {
- operational:
- "border-emerald-500/30 bg-emerald-500/10 text-emerald-200",
+ operational: "border-emerald-500/30 bg-emerald-500/10 text-emerald-200",
degraded: "border-yellow-500/30 bg-yellow-500/10 text-yellow-200",
outage: "border-red-500/40 bg-red-500/10 text-red-200",
};
@@ -71,7 +76,9 @@ export default function AdminStatusOverview({
-
+
@@ -113,9 +120,7 @@ export default function AdminStatusOverview({
Healthy services
- {services.length
- ? `${healthyServices}/${services.length}`
- : "—"}
+ {services.length ? `${healthyServices}/${services.length}` : "—"}
@@ -132,13 +137,18 @@ export default function AdminStatusOverview({
-
{service.name}
+
+ {service.name}
+
{service.responseTime} ms • {service.uptime} uptime
-
+
{service.status}
diff --git a/client/components/blog/BlogCategoryChips.tsx b/client/components/blog/BlogCategoryChips.tsx
index c92d1b4b..7bd259e1 100644
--- a/client/components/blog/BlogCategoryChips.tsx
+++ b/client/components/blog/BlogCategoryChips.tsx
@@ -7,7 +7,11 @@ interface BlogCategoryChipsProps {
onSelect: (id: string) => void;
}
-const BlogCategoryChips = ({ categories, selected, onSelect }: BlogCategoryChipsProps) => {
+const BlogCategoryChips = ({
+ categories,
+ selected,
+ onSelect,
+}: BlogCategoryChipsProps) => {
if (!categories.length) return null;
return (
diff --git a/client/components/blog/BlogHero.tsx b/client/components/blog/BlogHero.tsx
index 4292d1f7..437ccd7d 100644
--- a/client/components/blog/BlogHero.tsx
+++ b/client/components/blog/BlogHero.tsx
@@ -14,7 +14,13 @@ interface BlogHeroProps {
onViewAll?: () => void;
}
-const BlogHero = ({ featured, totalCount, search, onSearchChange, onViewAll }: BlogHeroProps) => {
+const BlogHero = ({
+ featured,
+ totalCount,
+ search,
+ onSearchChange,
+ onViewAll,
+}: BlogHeroProps) => {
return (
@@ -32,7 +38,9 @@ const BlogHero = ({ featured, totalCount, search, onSearchChange, onViewAll }: B
Ideas, updates, and behind-the-scenes craft from the AeThex team
- Explore engineering deep dives, platform updates, community spotlights, and changelog summaries. We publish what we learn building AeThex across games, cloud, and creator ecosystems.
+ Explore engineering deep dives, platform updates, community
+ spotlights, and changelog summaries. We publish what we learn
+ building AeThex across games, cloud, and creator ecosystems.
@@ -75,7 +83,9 @@ const BlogHero = ({ featured, totalCount, search, onSearchChange, onViewAll }: B
>
{featured.title}
-
{featured.excerpt}
+
+ {featured.excerpt}
+
{featured.author || "AeThex Team"}
@@ -93,13 +103,16 @@ const BlogHero = ({ featured, totalCount, search, onSearchChange, onViewAll }: B
- Read the full story
+
+ Read the full story
+
) : (
- We are preparing our latest feature article. Check back soon for fresh insights straight from the AeThex ship room.
+ We are preparing our latest feature article. Check back soon
+ for fresh insights straight from the AeThex ship room.
diff --git a/client/components/blog/BlogNewsletterSection.tsx b/client/components/blog/BlogNewsletterSection.tsx
index 4e9ac515..38b81bd4 100644
--- a/client/components/blog/BlogNewsletterSection.tsx
+++ b/client/components/blog/BlogNewsletterSection.tsx
@@ -15,9 +15,13 @@ const BlogNewsletterSection = () => {
-
Stay in the AeThex signal
+
+ Stay in the AeThex signal
+
- Subscribe for release notes, engineering write-ups, and community highlights. Expect one curated update every week—only the essentials.
+ Subscribe for release notes, engineering write-ups, and
+ community highlights. Expect one curated update every
+ week—only the essentials.
- By subscribing you agree to receive emails from AeThex. Unsubscribe anytime in a single click.
+ By subscribing you agree to receive emails from AeThex.
+ Unsubscribe anytime in a single click.
diff --git a/client/components/blog/BlogPostGrid.tsx b/client/components/blog/BlogPostGrid.tsx
index 186319f5..17cbb0dc 100644
--- a/client/components/blog/BlogPostGrid.tsx
+++ b/client/components/blog/BlogPostGrid.tsx
@@ -11,7 +11,11 @@ interface BlogPostGridProps {
emptyState?: React.ReactNode;
}
-const BlogPostGrid = ({ posts, placeholderImage = "/placeholder.svg", emptyState }: BlogPostGridProps) => {
+const BlogPostGrid = ({
+ posts,
+ placeholderImage = "/placeholder.svg",
+ emptyState,
+}: BlogPostGridProps) => {
if (!posts.length) {
return (
@@ -38,25 +42,39 @@ const BlogPostGrid = ({ posts, placeholderImage = "/placeholder.svg", emptyState
) : (
-
+
)}
-
+
{post.category || "General"}
{post.readTime ? (
- {post.readTime}
+
+ {post.readTime}
+
) : null}
-
+
{post.title}
- {post.excerpt}
+
+ {post.excerpt}
+
@@ -81,7 +99,10 @@ const BlogPostGrid = ({ posts, placeholderImage = "/placeholder.svg", emptyState
{post.comments?.toLocaleString() ?? 0}
-
+
Read article
diff --git a/client/components/blog/BlogTrendingRail.tsx b/client/components/blog/BlogTrendingRail.tsx
index d1869140..008cfcbf 100644
--- a/client/components/blog/BlogTrendingRail.tsx
+++ b/client/components/blog/BlogTrendingRail.tsx
@@ -16,8 +16,12 @@ const BlogTrendingRail = ({ posts }: BlogTrendingRailProps) => {
-
Trending now
-
High-signal reads across AeThex
+
+ Trending now
+
+
+ High-signal reads across AeThex
+
Hot topics
@@ -40,7 +44,9 @@ const BlogTrendingRail = ({ posts }: BlogTrendingRailProps) => {
>
{post.title}
- {post.excerpt}
+
+ {post.excerpt}
+
{post.author || "AeThex Team"}
diff --git a/client/components/notifications/NotificationBell.tsx b/client/components/notifications/NotificationBell.tsx
index 1578b1ed..6a5946bd 100644
--- a/client/components/notifications/NotificationBell.tsx
+++ b/client/components/notifications/NotificationBell.tsx
@@ -38,7 +38,10 @@ interface AethexNotification {
read: boolean | null;
}
-const typeIconMap: Record
> = {
+const typeIconMap: Record<
+ string,
+ React.ComponentType<{ className?: string }>
+> = {
success: CheckCircle2,
warning: AlertTriangle,
error: XCircle,
@@ -54,7 +57,11 @@ const typeAccentMap: Record = {
default: "text-aethex-300",
};
-export default function NotificationBell({ className }: { className?: string }) {
+export default function NotificationBell({
+ className,
+}: {
+ className?: string;
+}) {
const { user } = useAuth();
const [notifications, setNotifications] = useState([]);
const [loading, setLoading] = useState(false);
@@ -73,7 +80,9 @@ export default function NotificationBell({ className }: { className?: string })
.getUserNotifications(user.id)
.then((data) => {
if (!isActive) return;
- setNotifications(Array.isArray(data) ? (data as AethexNotification[]) : []);
+ setNotifications(
+ Array.isArray(data) ? (data as AethexNotification[]) : [],
+ );
})
.catch(() => {
if (!isActive) return;
@@ -88,7 +97,9 @@ export default function NotificationBell({ className }: { className?: string })
user.id,
(payload: any) => {
if (!isActive) return;
- const next = (payload?.new ?? payload) as AethexNotification | undefined;
+ const next = (payload?.new ?? payload) as
+ | AethexNotification
+ | undefined;
if (!next?.id) return;
setNotifications((prev) => {
@@ -139,7 +150,9 @@ export default function NotificationBell({ className }: { className?: string })
}
setNotifications((prev) => prev.map((n) => ({ ...n, read: true })));
try {
- await Promise.all(ids.map((id) => aethexNotificationService.markAsRead(id)));
+ await Promise.all(
+ ids.map((id) => aethexNotificationService.markAsRead(id)),
+ );
} catch {
// Soft fail silently
} finally {
@@ -222,7 +235,9 @@ export default function NotificationBell({ className }: { className?: string })
className="w-80 border-border/40 bg-background/95 backdrop-blur"
>
- Notifications
+
+ Notifications
+
{unreadCount > 0 ? (
{unreadCount} unread
@@ -248,11 +263,14 @@ export default function NotificationBell({ className }: { className?: string })
{loading ? (
- Loading notifications…
+ Loading
+ notifications…
) : notifications.length ? (
- {notifications.map((notification) => renderNotification(notification))}
+ {notifications.map((notification) =>
+ renderNotification(notification),
+ )}
) : (
diff --git a/client/contexts/AuthContext.tsx b/client/contexts/AuthContext.tsx
index 27854233..ebeea8c1 100644
--- a/client/contexts/AuthContext.tsx
+++ b/client/contexts/AuthContext.tsx
@@ -461,7 +461,9 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({
const payload = await response.json().catch(() => ({}));
if (!response.ok) {
- throw new Error(payload?.error || "Failed to queue verification email");
+ throw new Error(
+ payload?.error || "Failed to queue verification email",
+ );
}
emailSent = Boolean(payload?.sent);
diff --git a/client/pages/Admin.tsx b/client/pages/Admin.tsx
index 6523328e..3c15f52f 100644
--- a/client/pages/Admin.tsx
+++ b/client/pages/Admin.tsx
@@ -348,7 +348,8 @@ export default function Admin() {
}, [statusSnapshot]);
const blogReach = useMemo(
- () => resolvedBlogPosts.reduce((total, post) => total + (post.likes ?? 0), 0),
+ () =>
+ resolvedBlogPosts.reduce((total, post) => total + (post.likes ?? 0), 0),
[resolvedBlogPosts],
);
@@ -430,8 +431,8 @@ export default function Admin() {
trend: loadingPosts
? "Refreshing content…"
: blogHighlights.length
- ? `Latest: ${blogHighlights[0].title}`
- : "Curate new stories",
+ ? `Latest: ${blogHighlights[0].title}`
+ : "Curate new stories",
icon: PenTool,
tone: "purple" as const,
},
diff --git a/client/pages/Blog.tsx b/client/pages/Blog.tsx
index 64e460e6..d21e6431 100644
--- a/client/pages/Blog.tsx
+++ b/client/pages/Blog.tsx
@@ -14,7 +14,8 @@ import { Button } from "@/components/ui/button";
import { ArrowRight, Layers, ListFilter, Newspaper } from "lucide-react";
import type { BlogCategory, BlogPost } from "@/components/blog/types";
-const buildSlug = (post: BlogPost): string => post.slug || post.id?.toString() || "article";
+const buildSlug = (post: BlogPost): string =>
+ post.slug || post.id?.toString() || "article";
const normalizeCategory = (value?: string | null) =>
(value || "general")
@@ -43,10 +44,17 @@ const Blog = () => {
data = await res.json();
}
} catch (error) {
- console.warn("Failed to parse blog API response, falling back to Supabase", error);
+ console.warn(
+ "Failed to parse blog API response, falling back to Supabase",
+ error,
+ );
}
- if ((!Array.isArray(data) || !data.length) && import.meta.env.VITE_SUPABASE_URL && import.meta.env.VITE_SUPABASE_ANON_KEY) {
+ if (
+ (!Array.isArray(data) || !data.length) &&
+ import.meta.env.VITE_SUPABASE_URL &&
+ import.meta.env.VITE_SUPABASE_ANON_KEY
+ ) {
try {
const sbUrl = import.meta.env.VITE_SUPABASE_URL.replace(/\/$/, "");
const url = `${sbUrl}/rest/v1/blog_posts?select=slug,title,excerpt,author,date,read_time,category,image,likes,comments,published_at&order=published_at.desc&limit=50`;
@@ -76,8 +84,11 @@ const Blog = () => {
category: record.category ?? "General",
image: record.image ?? null,
likes: typeof record.likes === "number" ? record.likes : null,
- comments: typeof record.comments === "number" ? record.comments : null,
- trending: Boolean(record.trending) || (typeof record.likes === "number" && record.likes > 250),
+ comments:
+ typeof record.comments === "number" ? record.comments : null,
+ trending:
+ Boolean(record.trending) ||
+ (typeof record.likes === "number" && record.likes > 250),
body: record.body_html ?? record.body ?? null,
}));
setPosts(mapped);
@@ -103,7 +114,8 @@ const Blog = () => {
const query = searchQuery.trim().toLowerCase();
return dataset.filter((post) => {
const matchesCategory =
- selectedCategory === "all" || normalizeCategory(post.category) === selectedCategory;
+ selectedCategory === "all" ||
+ normalizeCategory(post.category) === selectedCategory;
if (!matchesCategory) return false;
if (!query) return true;
@@ -119,12 +131,16 @@ const Blog = () => {
if (!filteredPosts.length) {
return dataset.find((post) => post.trending) ?? dataset[0] ?? null;
}
- return filteredPosts.find((post) => post.trending) ?? filteredPosts[0] ?? null;
+ return (
+ filteredPosts.find((post) => post.trending) ?? filteredPosts[0] ?? null
+ );
}, [dataset, filteredPosts]);
const displayedPosts = useMemo(() => {
if (!featuredPost) return filteredPosts;
- return filteredPosts.filter((post) => buildSlug(post) !== buildSlug(featuredPost));
+ return filteredPosts.filter(
+ (post) => buildSlug(post) !== buildSlug(featuredPost),
+ );
}, [filteredPosts, featuredPost]);
const trendingPosts = useMemo(() => {
@@ -158,7 +174,9 @@ const Blog = () => {
() => [
{
label: "Teams publishing",
- value: new Set(dataset.map((post) => (post.author || "AeThex Team").split(" ")[0])).size,
+ value: new Set(
+ dataset.map((post) => (post.author || "AeThex Team").split(" ")[0]),
+ ).size,
helper: "Active contributors this month",
icon:
,
},
@@ -205,9 +223,16 @@ const Blog = () => {
Filter by track
-
Navigate the AeThex knowledge graph
+
+ Navigate the AeThex knowledge graph
+
-
+
Reset filters
@@ -235,9 +260,15 @@ const Blog = () => {
{insight.icon}
-
{insight.label}
-
{insight.value}
-
{insight.helper}
+
+ {insight.label}
+
+
+ {insight.value}
+
+
+ {insight.helper}
+
@@ -249,10 +280,18 @@ const Blog = () => {
-
Latest updates
-
Fresh from the AeThex ship room
+
+ Latest updates
+
+
+ Fresh from the AeThex ship room
+
-
+
View changelog
@@ -271,14 +310,23 @@ const Blog = () => {
-
Explore more
-
Dive into AeThex documentation
+
+ Explore more
+
+
+ Dive into AeThex documentation
+
- Looking for implementation guides, deployment recipes, or program onboarding materials?
- Visit our documentation hub for developer tutorials, platform references, and community playbooks.
+ Looking for implementation guides, deployment recipes, or
+ program onboarding materials? Visit our documentation hub
+ for developer tutorials, platform references, and community
+ playbooks.
-
+
Open documentation hub
diff --git a/client/pages/Changelog.tsx b/client/pages/Changelog.tsx
index 9c65f205..d6c1d66e 100644
--- a/client/pages/Changelog.tsx
+++ b/client/pages/Changelog.tsx
@@ -1,6 +1,12 @@
import { useState } from "react";
import Layout from "@/components/Layout";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
@@ -34,7 +40,7 @@ interface ChangelogEntry {
id: string;
version: string;
date: string;
- type: 'major' | 'minor' | 'patch';
+ type: "major" | "minor" | "patch";
category: string;
title: string;
description: string;
@@ -44,9 +50,9 @@ interface ChangelogEntry {
}
interface ChangelogItem {
- type: 'added' | 'improved' | 'fixed' | 'removed' | 'security';
+ type: "added" | "improved" | "fixed" | "removed" | "security";
description: string;
- impact: 'high' | 'medium' | 'low';
+ impact: "high" | "medium" | "low";
}
export const changelogEntries: ChangelogEntry[] = [
@@ -57,126 +63,162 @@ export const changelogEntries: ChangelogEntry[] = [
type: "major",
category: "Platform Enhancement",
title: "Major Platform Improvements & New Features",
- description: "Comprehensive platform upgrade with new dashboard features, improved user experience, and enhanced system monitoring capabilities.",
+ description:
+ "Comprehensive platform upgrade with new dashboard features, improved user experience, and enhanced system monitoring capabilities.",
author: "AeThex Development Team",
pullRequest: "#121e8c26",
changes: [
{
type: "added",
- description: "New comprehensive Profile system with overseer dashboard and cross-site communication monitoring",
- impact: "high"
- },
- {
- type: "added",
- description: "System Status page with real-time monitoring of all AeThex services and infrastructure",
- impact: "high"
+ description:
+ "New comprehensive Profile system with overseer dashboard and cross-site communication monitoring",
+ impact: "high",
},
{
type: "added",
- description: "Comprehensive Tutorials library with categorized learning content and filtering capabilities",
- impact: "medium"
+ description:
+ "System Status page with real-time monitoring of all AeThex services and infrastructure",
+ impact: "high",
},
{
type: "added",
- description: "Nested Documentation routing system with improved navigation and breadcrumbs",
- impact: "medium"
+ description:
+ "Comprehensive Tutorials library with categorized learning content and filtering capabilities",
+ impact: "medium",
},
{
type: "added",
- description: "Documentation-specific tutorials section with interactive content types",
- impact: "medium"
+ description:
+ "Nested Documentation routing system with improved navigation and breadcrumbs",
+ impact: "medium",
},
{
type: "added",
- description: "Login access options on onboarding page to prevent duplicate account creation",
- impact: "medium"
+ description:
+ "Documentation-specific tutorials section with interactive content types",
+ impact: "medium",
+ },
+ {
+ type: "added",
+ description:
+ "Login access options on onboarding page to prevent duplicate account creation",
+ impact: "medium",
},
{
type: "improved",
- description: "Enhanced navigation system with user-specific menu items when authenticated",
- impact: "medium"
+ description:
+ "Enhanced navigation system with user-specific menu items when authenticated",
+ impact: "medium",
},
{
type: "improved",
- description: "Dashboard user interface with proper profile data integration and XP progression",
- impact: "medium"
+ description:
+ "Dashboard user interface with proper profile data integration and XP progression",
+ impact: "medium",
},
{
type: "improved",
- description: "Authentication flow with better error handling and redirect logic",
- impact: "high"
+ description:
+ "Authentication flow with better error handling and redirect logic",
+ impact: "high",
},
{
type: "fixed",
- description: "Resolved Dashboard infinite loading screen issue when accessing without authentication",
- impact: "high"
+ description:
+ "Resolved Dashboard infinite loading screen issue when accessing without authentication",
+ impact: "high",
},
{
type: "fixed",
- description: "Fixed toast notification bouncing animations that were causing UI disruption",
- impact: "medium"
+ description:
+ "Fixed toast notification bouncing animations that were causing UI disruption",
+ impact: "medium",
},
{
type: "fixed",
- description: "Corrected database adapter table name mismatches and TypeScript compilation errors",
- impact: "high"
+ description:
+ "Corrected database adapter table name mismatches and TypeScript compilation errors",
+ impact: "high",
},
{
type: "fixed",
- description: "Resolved DNS configuration issues for custom domain deployment",
- impact: "medium"
+ description:
+ "Resolved DNS configuration issues for custom domain deployment",
+ impact: "medium",
},
{
type: "fixed",
- description: "Fixed user profile property access issues throughout the application",
- impact: "medium"
+ description:
+ "Fixed user profile property access issues throughout the application",
+ impact: "medium",
},
{
type: "security",
- description: "Enhanced authentication redirect security with proper session handling",
- impact: "high"
- }
- ]
- }
+ description:
+ "Enhanced authentication redirect security with proper session handling",
+ impact: "high",
+ },
+ ],
+ },
];
const getTypeIcon = (type: string) => {
switch (type) {
- case 'added': return
;
- case 'improved': return
;
- case 'fixed': return
;
- case 'removed': return
;
- case 'security': return
;
- default: return
;
+ case "added":
+ return
;
+ case "improved":
+ return
;
+ case "fixed":
+ return
;
+ case "removed":
+ return
;
+ case "security":
+ return
;
+ default:
+ return
;
}
};
const getTypeColor = (type: string) => {
switch (type) {
- case 'added': return 'bg-green-500';
- case 'improved': return 'bg-blue-500';
- case 'fixed': return 'bg-orange-500';
- case 'removed': return 'bg-red-500';
- case 'security': return 'bg-purple-500';
- default: return 'bg-gray-500';
+ case "added":
+ return "bg-green-500";
+ case "improved":
+ return "bg-blue-500";
+ case "fixed":
+ return "bg-orange-500";
+ case "removed":
+ return "bg-red-500";
+ case "security":
+ return "bg-purple-500";
+ default:
+ return "bg-gray-500";
}
};
const getVersionBadgeColor = (type: string) => {
switch (type) {
- case 'major': return 'bg-purple-600';
- case 'minor': return 'bg-blue-600';
- case 'patch': return 'bg-green-600';
- default: return 'bg-gray-600';
+ case "major":
+ return "bg-purple-600";
+ case "minor":
+ return "bg-blue-600";
+ case "patch":
+ return "bg-green-600";
+ default:
+ return "bg-gray-600";
}
};
const getImpactColor = (impact: string) => {
switch (impact) {
- case 'high': return 'text-red-400';
- case 'medium': return 'text-yellow-400';
- case 'low': return 'text-green-400';
- default: return 'text-gray-400';
+ case "high":
+ return "text-red-400";
+ case "medium":
+ return "text-yellow-400";
+ case "low":
+ return "text-green-400";
+ default:
+ return "text-gray-400";
}
};
@@ -185,20 +227,28 @@ export default function Changelog() {
const [selectedType, setSelectedType] = useState("all");
const [selectedCategory, setSelectedCategory] = useState("all");
- const filteredEntries = changelogEntries.filter(entry => {
- const matchesSearch = entry.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
- entry.description.toLowerCase().includes(searchTerm.toLowerCase()) ||
- entry.changes.some(change =>
- change.description.toLowerCase().includes(searchTerm.toLowerCase())
- );
+ const filteredEntries = changelogEntries.filter((entry) => {
+ const matchesSearch =
+ entry.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
+ entry.description.toLowerCase().includes(searchTerm.toLowerCase()) ||
+ entry.changes.some((change) =>
+ change.description.toLowerCase().includes(searchTerm.toLowerCase()),
+ );
const matchesType = selectedType === "all" || entry.type === selectedType;
- const matchesCategory = selectedCategory === "all" ||
- entry.category.toLowerCase().replace(/\s+/g, '-') === selectedCategory;
-
+ const matchesCategory =
+ selectedCategory === "all" ||
+ entry.category.toLowerCase().replace(/\s+/g, "-") === selectedCategory;
+
return matchesSearch && matchesType && matchesCategory;
});
- const categories = ["all", "platform-enhancement", "security", "performance", "ui-ux"];
+ const categories = [
+ "all",
+ "platform-enhancement",
+ "security",
+ "performance",
+ "ui-ux",
+ ];
const types = ["all", "major", "minor", "patch"];
return (
@@ -213,11 +263,15 @@ export default function Changelog() {
AeThex Changelog
- Track the latest updates, improvements, and fixes to the AeThex platform
+ Track the latest updates, improvements, and fixes to the
+ AeThex platform
-
+
View on GitHub
@@ -227,7 +281,7 @@ export default function Changelog() {
-
+
{/* Stats */}
@@ -235,21 +289,27 @@ export default function Changelog() {
Total Releases
-
{changelogEntries.length}
+
+ {changelogEntries.length}
+
-
+
New Features
- {changelogEntries.reduce((acc, entry) =>
- acc + entry.changes.filter(c => c.type === 'added').length, 0
+ {changelogEntries.reduce(
+ (acc, entry) =>
+ acc +
+ entry.changes.filter((c) => c.type === "added")
+ .length,
+ 0,
)}
@@ -257,15 +317,19 @@ export default function Changelog() {
-
+
Bug Fixes
- {changelogEntries.reduce((acc, entry) =>
- acc + entry.changes.filter(c => c.type === 'fixed').length, 0
+ {changelogEntries.reduce(
+ (acc, entry) =>
+ acc +
+ entry.changes.filter((c) => c.type === "fixed")
+ .length,
+ 0,
)}
@@ -273,15 +337,19 @@ export default function Changelog() {
-
+
Improvements
- {changelogEntries.reduce((acc, entry) =>
- acc + entry.changes.filter(c => c.type === 'improved').length, 0
+ {changelogEntries.reduce(
+ (acc, entry) =>
+ acc +
+ entry.changes.filter((c) => c.type === "improved")
+ .length,
+ 0,
)}
@@ -310,9 +378,11 @@ export default function Changelog() {
onChange={(e) => setSelectedType(e.target.value)}
className="bg-slate-800/50 border-slate-600 text-white rounded-md px-3 py-2"
>
- {types.map(type => (
+ {types.map((type) => (
- {type === 'all' ? 'All Types' : type.charAt(0).toUpperCase() + type.slice(1)}
+ {type === "all"
+ ? "All Types"
+ : type.charAt(0).toUpperCase() + type.slice(1)}
))}
@@ -321,13 +391,17 @@ export default function Changelog() {
onChange={(e) => setSelectedCategory(e.target.value)}
className="bg-slate-800/50 border-slate-600 text-white rounded-md px-3 py-2"
>
- {categories.map(category => (
+ {categories.map((category) => (
- {category === 'all' ? 'All Categories' :
- category.split('-').map(word =>
- word.charAt(0).toUpperCase() + word.slice(1)
- ).join(' ')
- }
+ {category === "all"
+ ? "All Categories"
+ : category
+ .split("-")
+ .map(
+ (word) =>
+ word.charAt(0).toUpperCase() + word.slice(1),
+ )
+ .join(" ")}
))}
@@ -338,11 +412,16 @@ export default function Changelog() {
{/* Changelog Entries */}
{filteredEntries.map((entry, index) => (
-
+
-
+
v{entry.version}
@@ -350,68 +429,83 @@ export default function Changelog() {
- {new Date(entry.date).toLocaleDateString('en-US', {
- year: 'numeric',
- month: 'long',
- day: 'numeric'
+ {new Date(entry.date).toLocaleDateString("en-US", {
+ year: "numeric",
+ month: "long",
+ day: "numeric",
})}
{entry.pullRequest && (
-
+
{entry.pullRequest}
)}
-
+
{entry.title}
{entry.description}
-
+
By {entry.author}
-
+
{/* Group changes by type */}
- {['added', 'improved', 'fixed', 'security', 'removed'].map(changeType => {
- const changesOfType = entry.changes.filter(change => change.type === changeType);
- if (changesOfType.length === 0) return null;
-
- return (
-
-
- {getTypeIcon(changeType)}
-
- {changeType} ({changesOfType.length})
-
+ {["added", "improved", "fixed", "security", "removed"].map(
+ (changeType) => {
+ const changesOfType = entry.changes.filter(
+ (change) => change.type === changeType,
+ );
+ if (changesOfType.length === 0) return null;
+
+ return (
+
+
+ {getTypeIcon(changeType)}
+
+ {changeType} ({changesOfType.length})
+
+
+
+ {changesOfType.map((change, changeIndex) => (
+
+
+
+
+ {change.description}
+
+
+ {change.impact} impact
+
+
+
+ ))}
+
-
- {changesOfType.map((change, changeIndex) => (
-
-
-
-
{change.description}
-
- {change.impact} impact
-
-
-
- ))}
-
-
- );
- })}
+ );
+ },
+ )}
@@ -426,7 +520,8 @@ export default function Changelog() {
No changelog entries found
- Try adjusting your search terms or filters to find what you're looking for.
+ Try adjusting your search terms or filters to find what you're
+ looking for.
@@ -440,10 +535,14 @@ export default function Changelog() {
Stay Updated
- Follow our development progress and get notified about new releases
+ Follow our development progress and get notified about new
+ releases
-
+
Watch on GitHub
diff --git a/client/pages/Login.tsx b/client/pages/Login.tsx
index 8f982c31..d19e63cc 100644
--- a/client/pages/Login.tsx
+++ b/client/pages/Login.tsx
@@ -35,7 +35,9 @@ export default function Login() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [fullName, setFullName] = useState("");
- const [manualVerificationLink, setManualVerificationLink] = useState(null);
+ const [manualVerificationLink, setManualVerificationLink] = useState<
+ string | null
+ >(null);
const navigate = useNavigate();
const { signIn, signUp, signInWithOAuth, user, loading, profileComplete } =
useAuth();
@@ -99,7 +101,8 @@ export default function Login() {
console.error("Authentication error:", error);
toastError({
title: "Authentication failed",
- description: error?.message || "Something went wrong. Please try again.",
+ description:
+ error?.message || "Something went wrong. Please try again.",
});
} finally {
setIsLoading(false);
@@ -203,7 +206,13 @@ export default function Login() {
size="sm"
variant="outline"
className="mt-3 border-aethex-400/40"
- onClick={() => window.open(manualVerificationLink, "_blank", "noopener")}
+ onClick={() =>
+ window.open(
+ manualVerificationLink,
+ "_blank",
+ "noopener",
+ )
+ }
>
Open verification link
diff --git a/server/email.ts b/server/email.ts
index c802a802..ceb8d0d7 100644
--- a/server/email.ts
+++ b/server/email.ts
@@ -1,8 +1,10 @@
import { Resend } from "resend";
const resendApiKey = process.env.RESEND_API_KEY;
-const defaultFromAddress = process.env.RESEND_FROM_EMAIL ?? "AeThex OS ";
-const verifySupportEmail = process.env.VERIFY_SUPPORT_EMAIL ?? "support@aethex.biz";
+const defaultFromAddress =
+ process.env.RESEND_FROM_EMAIL ?? "AeThex OS ";
+const verifySupportEmail =
+ process.env.VERIFY_SUPPORT_EMAIL ?? "support@aethex.biz";
const resendClient = resendApiKey ? new Resend(resendApiKey) : null;
@@ -42,7 +44,9 @@ export const emailService = {
`;
- const text = [`Welcome to AeThex, ${safeName}!`, "",
+ const text = [
+ `Welcome to AeThex, ${safeName}!`,
+ "",
"Use the link below to verify your account:",
verificationUrl,
"",