+
+
+
Contacts
+
-
- {contacts.map((contact) => (
-
-
-
-
- {contact.firstName && contact.lastName
- ? `${contact.firstName} ${contact.lastName}`
- : contact.screenName || 'Unnamed Contact'}
-
- {contact.screenName && (
-
@{contact.screenName}
- )}
- {contact.email && (
-
{contact.email}
- )}
- {contact.nostrPubkey && (
-
- {contact.nostrPubkey}
-
- )}
-
-
-
Edit
-
-
-
- {contact.metadata && typeof contact.metadata === 'object' && 'bio' in contact.metadata && typeof contact.metadata.bio === 'string' && (
-
{contact.metadata.bio}
- )}
-
- ))}
+
+ {contacts.map((contact) => (
+
+ ))}
+
);
diff --git a/app/globals.css b/app/globals.css
index 6b717ad..4f1c14a 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -3,13 +3,13 @@
@tailwind utilities;
:root {
- --background: #ffffff;
- --foreground: #171717;
+ --background: #030404;
+ --foreground: #ededed;
}
@media (prefers-color-scheme: dark) {
:root {
- --background: #0a0a0a;
+ --background: #030404;
--foreground: #ededed;
}
}
diff --git a/app/layout.tsx b/app/layout.tsx
index 7d1e0eb..baeb15e 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -2,7 +2,8 @@ import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { NostrProvider } from "./contexts/NostrContext";
-import Header from "./components/Header";
+import Sidebar from "./components/Sidebar";
+import TopNav from "./components/TopNav";
const inter = Inter({ subsets: ["latin"] });
@@ -18,10 +19,19 @@ export default function RootLayout({
}) {
return (
-
+
-
- {children}
+
+
+
+
+
+
+
+ {children}
+
+
+
diff --git a/app/lib/iconTokens.ts b/app/lib/iconTokens.ts
new file mode 100644
index 0000000..cf757fa
--- /dev/null
+++ b/app/lib/iconTokens.ts
@@ -0,0 +1,42 @@
+export const iconTokens = {
+ dashboard: {
+ default: 'https://www.figma.com/api/mcp/asset/7ea22fe7-76f3-4dcd-be2a-27584735bf3e',
+ green: 'https://www.figma.com/api/mcp/asset/46fe45e5-90ae-4730-b5f5-6775c3ea68b7',
+ dark: 'https://www.figma.com/api/mcp/asset/a4ec5af4-7202-4a2c-af55-4f15dddc4549',
+ },
+ prisms: {
+ default: 'https://www.figma.com/api/mcp/asset/344137cd-61ab-4c91-80d3-746b4b1078ef',
+ green: 'https://www.figma.com/api/mcp/asset/6c56fea7-8bb6-4c02-be2c-fa73a3c6e210',
+ dark: 'https://www.figma.com/api/mcp/asset/e9890cf3-3675-49e7-8a57-e15013aed9d5',
+ },
+ contacts: {
+ default: 'https://www.figma.com/api/mcp/asset/db895cc0-2873-4f73-a16f-71332b53de60',
+ green: 'https://www.figma.com/api/mcp/asset/af5bddfe-c935-4178-a465-7b22f4a480c5',
+ dark: 'https://www.figma.com/api/mcp/asset/425d7d31-b102-4dfd-98bd-6e9f84ab25b0',
+ },
+ notifications: {
+ default: 'https://www.figma.com/api/mcp/asset/9bef6dcd-9734-44fa-b3c8-fda66e0a8bb7',
+ green: 'https://www.figma.com/api/mcp/asset/7023b275-ef0d-485b-846e-a823595fab0c',
+ dark: 'https://www.figma.com/api/mcp/asset/efde19ab-cd3c-4d42-a31a-827179fc0433',
+ },
+ settings: {
+ default: 'https://www.figma.com/api/mcp/asset/f1c526ef-385e-49c0-95f7-2ee7831d0d1f',
+ variant2: 'https://www.figma.com/api/mcp/asset/6d2b67c0-1f7e-4a36-b5b3-20fb8eaede33',
+ variant3: 'https://www.figma.com/api/mcp/asset/55e572ed-04e4-47ca-9149-5815e4f6e3e9',
+ },
+ wallet: {
+ default: 'https://www.figma.com/api/mcp/asset/9b443623-e832-4d0e-a38c-850d8be7a35e',
+ green: 'https://www.figma.com/api/mcp/asset/f5bfa230-d75d-46fe-a700-2bab54cd9fee',
+ },
+ finance: {
+ default: 'https://www.figma.com/api/mcp/asset/89d6edc7-18cd-4d29-97b3-db4116db9ed0',
+ variant2: 'https://www.figma.com/api/mcp/asset/22c366a9-5a17-4eb7-9da8-248d0a7a4e76',
+ variant3: 'https://www.figma.com/api/mcp/asset/6bd0f1ab-4945-47da-bf52-f72129f762d9',
+ },
+ vector: {
+ default: 'https://www.figma.com/api/mcp/asset/0ca23d71-1965-41a9-b1bb-42fc1827f05a',
+ variant2: 'https://www.figma.com/api/mcp/asset/329bbee7-c73b-433d-97e4-dd2a7179ee28',
+ variant3: 'https://www.figma.com/api/mcp/asset/45f3e1e8-dce4-4de1-904a-9cbda44f996e',
+ },
+} as const;
+
diff --git a/app/node/layout.tsx b/app/node/layout.tsx
index e9986c6..d73a27d 100644
--- a/app/node/layout.tsx
+++ b/app/node/layout.tsx
@@ -1,14 +1,7 @@
-import Header from "../components/Header";
-
export default function NodeLayout({
children,
}: {
children: React.ReactNode;
}) {
- return (
- <>
-
- {children}
- >
- );
+ return <>{children}>;
}
\ No newline at end of file
diff --git a/app/node/page.tsx b/app/node/page.tsx
index ab8c313..968b0a0 100644
--- a/app/node/page.tsx
+++ b/app/node/page.tsx
@@ -2,10 +2,12 @@ import PhoenixInfo from "../components/PhoenixInfo";
export default function NodePage() {
return (
-
- Node Information
-
-
+
+
);
diff --git a/app/page.tsx b/app/page.tsx
index 82662ee..1e70147 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,10 +1,99 @@
'use client';
+import { useState, useEffect } from 'react';
import { useNostr } from "./contexts/NostrContext";
import Button from "./components/Button";
+import PrismFaceCard from "./components/PrismFaceCard";
+import PrismHeadingCard from "./components/PrismHeadingCard";
+import PrismInfoCard from "./components/PrismInfoCard";
+import TransactionTable from "./components/TransactionTable";
+
+interface Prism {
+ id: string;
+ name: string;
+ slug: string;
+ description: string | null;
+ active: boolean;
+ createdAt: string;
+ splits?: Array<{
+ paymentDestination: {
+ contact: {
+ id: string;
+ };
+ };
+ }>;
+}
+
+interface Contact {
+ id: string;
+ firstName: string | null;
+ lastName: string | null;
+ screenName: string | null;
+ email: string | null;
+}
export default function Home() {
const { publicKey, login } = useNostr();
+ const [prisms, setPrisms] = useState
([]);
+ const [contacts, setContacts] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [selectedPrismId, setSelectedPrismId] = useState('all');
+ const [dateRange, setDateRange] = useState<{ start: Date; end: Date }>(() => {
+ const today = new Date();
+ const startOfWeek = new Date(today);
+ startOfWeek.setDate(today.getDate() - today.getDay());
+ const endOfWeek = new Date(startOfWeek);
+ endOfWeek.setDate(startOfWeek.getDate() + 6);
+ return { start: startOfWeek, end: endOfWeek };
+ });
+
+ useEffect(() => {
+ if (publicKey) {
+ fetchPrisms();
+ fetchContacts();
+ }
+ }, [publicKey]);
+
+ const fetchContacts = async () => {
+ try {
+ const response = await fetch('/api/contacts');
+ if (response.ok) {
+ const data = await response.json();
+ setContacts(data);
+ }
+ } catch (err) {
+ console.error('Error fetching contacts:', err);
+ }
+ };
+
+ const fetchPrisms = async () => {
+ setLoading(true);
+ try {
+ const response = await fetch('/api/prisms');
+ if (response.ok) {
+ const data = await response.json();
+ // Fetch detailed data for each prism to get member count
+ const prismsWithDetails = await Promise.all(
+ data.map(async (prism: Prism) => {
+ try {
+ const detailResponse = await fetch(`/api/prisms/${prism.id}`);
+ if (detailResponse.ok) {
+ return await detailResponse.json();
+ }
+ return prism;
+ } catch {
+ return prism;
+ }
+ })
+ );
+ setPrisms(prismsWithDetails);
+ }
+ } catch (err) {
+ console.error('Error fetching prisms:', err);
+ } finally {
+ setLoading(false);
+ }
+ };
const handleLogin = async () => {
try {
@@ -14,16 +103,108 @@ export default function Home() {
}
};
+ // Calculate member count from splits
+ const getMemberCount = (prism: Prism): number => {
+ if (!prism.splits) return 0;
+ const uniqueContacts = new Set(
+ prism.splits.map(split => split.paymentDestination.contact.id)
+ );
+ return uniqueContacts.size;
+ };
+
+ // Calculate amounts based on selected prism and date range
+ // TODO: Replace with actual API calls to get transaction data
+ const calculateAmounts = () => {
+ // For now, return placeholder values
+ // In a real implementation, you would:
+ // 1. Filter transactions by selectedPrismId and dateRange
+ // 2. Calculate totalCollected, totalDispatched, and pending
+ return {
+ totalCollected: 412000.95,
+ totalDispatched: 412000.95,
+ pending: 0,
+ };
+ };
+
+ const amounts = calculateAmounts();
+
return (
{publicKey ? (
// Logged in view
-
-
-
Welcome to Aurora
-
- Your lightning prism management interface. Navigate through the menu to access different features.
-
+
+
+ {/* Welcome Section */}
+
+
+
Welcome to Aurora
+
+ Split any payment across wallets or accounts instantly, transparently, and securely.
+
+
+
+ {/* Info Cards */}
+
+
({ id: p.id, name: p.name }))}
+ selectedPrismId={selectedPrismId}
+ onPrismChange={setSelectedPrismId}
+ dateRange={dateRange}
+ onDateRangeChange={setDateRange}
+ />
+
+
+
+ {/* Hot Prisms Section */}
+
+
+
+ {/* Prism Cards Grid */}
+ {loading ? (
+
+ {[1, 2, 3, 4, 5].map((i) => (
+
+ ))}
+
+ ) : prisms.length > 0 ? (
+
+ {prisms.map((prism) => (
+
+ ))}
+
+ ) : (
+
+
No prisms found.
+
+ Create your first prism to get started.
+
+
+ )}
+
+
+ {/* Transaction Table */}
+
+ ({ id: p.id, name: p.name }))}
+ contacts={contacts}
+ />
+
) : (
diff --git a/app/prisms/[id]/page.tsx b/app/prisms/[id]/page.tsx
index 38949d9..ef8e3e1 100644
--- a/app/prisms/[id]/page.tsx
+++ b/app/prisms/[id]/page.tsx
@@ -93,10 +93,10 @@ export default function PrismPage({
if (loading) {
return (
-
-
+
+
-
+
@@ -110,10 +110,10 @@ export default function PrismPage({
if (!prism) {
return (
-
-
+
+
-
Prism Not Found
+
Prism Not Found
The prism you're looking for doesn't exist or you don't have permission to view it.
diff --git a/app/prisms/new/page.tsx b/app/prisms/new/page.tsx
index 0c5042b..cfeb274 100644
--- a/app/prisms/new/page.tsx
+++ b/app/prisms/new/page.tsx
@@ -185,10 +185,10 @@ export default function NewPrismPage() {
};
return (
-
-
-
-
Create New Prism
+
+
+
+
Create New Prism