Skip to content
Open
3 changes: 3 additions & 0 deletions contract/contracts/hello-world/src/autoshare_logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use crate::base::events::{
AdminTransferred, AuditAction, AuditRecordAppended, AuthorizationFailure, AutoshareCreated,
AutoshareUpdated, BatchNotificationsCreated, CategoryRegistered, ContractPaused,
ContractUnpaused, GroupActivated, GroupDeactivated, NotificationCategory, NotificationExpired,
NotificationPriority, NotificationRevoked, NotificationScheduled,
NotificationExtended, NotificationPriority, NotificationRevoked, NotificationScheduled,
ScheduledNotificationCancelled, Withdrawal,
NotificationPriority, NotificationRevoked, NotificationScheduled, ScheduledNotificationCancelled,
Withdrawal, BatchProcessingCompleted,
NotificationExtended, NotificationLimitsConfigured, NotificationPriority, NotificationRevoked,
Expand Down
95 changes: 95 additions & 0 deletions dashboard/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,100 @@
import { useEffect, useMemo, useState } from 'react';
import { EventExplorerPage } from './pages/EventExplorerPage';
import { NotificationPreferencesPage } from './pages/NotificationPreferencesPage';

const VALID_TAB_KEYS = ['explorer', 'preferences'] as const;

type TabKey = (typeof VALID_TAB_KEYS)[number];

function parseActiveTab(search: string): TabKey {
const params = new URLSearchParams(search);
const tab = params.get('tab');
return VALID_TAB_KEYS.includes(tab as TabKey) ? (tab as TabKey) : 'explorer';
}

export function App() {
const initialSearch = typeof window !== 'undefined' ? window.location.search : '';
const [activeTab, setActiveTab] = useState<TabKey>(() => parseActiveTab(initialSearch));

useEffect(() => {
if (typeof window === 'undefined') {
return;
}

const handlePopState = () => {
setActiveTab(parseActiveTab(window.location.search));
};

window.addEventListener('popstate', handlePopState);
return () => window.removeEventListener('popstate', handlePopState);
}, []);

useEffect(() => {
if (typeof window === 'undefined') {
return;
}

const params = new URLSearchParams(window.location.search);
params.set('tab', activeTab);
window.history.replaceState({}, '', `${window.location.pathname}?${params.toString()}`);
}, [activeTab]);

const tabLabel = useMemo(
() => (activeTab === 'preferences' ? 'Notification Preferences' : 'Event Explorer'),
[activeTab]
);

return (
<div className="app">
<header className="app__topbar">
<div className="app__brand">
<p className="app__brand-eyebrow">Notify Chain</p>
<h1>{tabLabel}</h1>
</div>

<nav className="app__nav" aria-label="Dashboard tabs">
<button
type="button"
className={`app__tab ${activeTab === 'explorer' ? 'app__tab--active' : ''}`}
import { useState } from 'react';
import { EventExplorerPage } from './pages/EventExplorerPage';
import { ExportHistoryPage } from './pages/ExportHistoryPage';

export function App() {
const [activeTab, setActiveTab] = useState<'explorer' | 'exports'>('explorer');

return (
<div className="app">
<nav className="nav-header">
<span className="nav-brand">Notify-Chain</span>
<div className="nav-tabs">
<button
type="button"
className={`nav-tab-btn ${activeTab === 'explorer' ? 'nav-tab-btn--active' : ''}`}
onClick={() => setActiveTab('explorer')}
>
Event Explorer
</button>
<button
type="button"
className={`app__tab ${activeTab === 'preferences' ? 'app__tab--active' : ''}`}
onClick={() => setActiveTab('preferences')}
>
Notification Preferences
</button>
</nav>
</header>

{activeTab === 'preferences' ? <NotificationPreferencesPage /> : <EventExplorerPage />}
className={`nav-tab-btn ${activeTab === 'exports' ? 'nav-tab-btn--active' : ''}`}
onClick={() => setActiveTab('exports')}
>
Export Center
</button>
</div>
</nav>

{activeTab === 'explorer' ? <EventExplorerPage /> : <ExportHistoryPage />}
import { NotificationTimelineView } from './components/NotificationTimelineView';
import { ActivityFeed } from './components/ActivityFeed';
import { ExportHistoryPage } from './pages/ExportHistoryPage';
Expand Down
Loading
Loading