Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions frontend/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,39 @@
gap: 2rem;
}

.header-content {
max-width: 1200px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
gap: 2rem;
}

.logo h1 {
font-size: 1.5rem;
margin: 0;
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}

.logo .tagline {
font-size: 0.875rem;
color: var(--text-secondary);
margin: 0;
}

.header-content {
max-width: 1200px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
gap: 2rem;
}

.logo h1 {
font-size: 1.5rem;
margin: 0;
Expand Down
164 changes: 0 additions & 164 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,164 +0,0 @@
import { useState, useMemo } from 'react'
import { useAccount } from 'wagmi'
import { Header } from './components/Header'
import { PiggyBankDashboard } from './components/PiggyBankDashboard'
import { WalletConnectPage } from './components/WalletConnectPage'
import { AdminDashboard } from './components/AdminDashboard'
import { TransactionToast } from './components/TransactionToast'
import { MobileNavigation } from './components/MobileNavigation'
import { NotificationProvider, NotificationContainer } from './components/SecureNotification'
import { ErrorBoundary } from './components/ErrorBoundary'
import { useWalletHistory } from './hooks/useWalletHistory'
import { usePiggyBank } from './hooks/usePiggyBank'
import { useMobile, useTouchDevice } from './hooks/useMobile'
import { DebugPage } from './components/DebugPage'
import './App.css'
import './styles/walletConnect.css'
import './styles/saveForLater.css'
import './styles/mobile.css'

type Page = 'home' | 'wallet' | 'admin' | 'debug'

function App() {
const { isConnected, address } = useAccount()
const [currentPage, setCurrentPage] = useState<Page>('home')
const { owner } = usePiggyBank()

// Track wallet connection history
useWalletHistory()

// Check if current user is admin
const isAdmin = useMemo(() => {
if (address && owner) {
return address.toLowerCase() === owner.toLowerCase()
}
return false
}, [address, owner])

return (
<ErrorBoundary level="critical" showDetails={process.env.NODE_ENV === 'development'}>
<NotificationProvider>
<div className="app">
<NotificationContainer />
<TransactionToast />

<div className="header-wrapper">
<ErrorBoundary level="component">
<Header />
</ErrorBoundary>
{/* Mobile Navigation */}
{isMobile && (
<ErrorBoundary level="component">
<MobileNavigation
currentPage={currentPage}
onPageChange={(page) => setCurrentPage(page as Page)}
isAdmin={isAdmin}
/>
</ErrorBoundary>
)}
</div>

{/* Desktop Navigation */}
{!isMobile && (
<nav className="app-nav">
<ErrorBoundary level="component">
<button
className={`nav-btn ${currentPage === 'home' ? 'active' : ''}`}
onClick={() => setCurrentPage('home')}
>
🏠 Home
</button>
<button
className={`nav-btn ${currentPage === 'wallet' ? 'active' : ''}`}
onClick={() => setCurrentPage('wallet')}
>
🔗 Wallet Connect
</button>
{isAdmin && (
<button
className={`nav-btn ${currentPage === 'admin' ? 'active' : ''}`}
onClick={() => setCurrentPage('admin')}
>
👑 Admin
</button>
)}
{process.env.NODE_ENV === 'development' && (
<button
className={`nav-btn ${currentPage === 'debug' ? 'active' : ''}`}
onClick={() => setCurrentPage('debug')}
>
🔧 Debug
</button>
)}
</ErrorBoundary>
</nav>
)}

<main className="main-content">
{currentPage === 'wallet' ? (
<ErrorBoundary level="page">
<WalletConnectPage />
</ErrorBoundary>
) : !isConnected ? (
<ErrorBoundary level="page">
<div className="connect-prompt">
<div className="connect-card">
<h2>Welcome to Ajo PiggyBank</h2>
<p>A decentralized savings application on Base blockchain</p>
<div className="features">
<ErrorBoundary level="component">
<div className="feature">
<span className="icon">🔒</span>
<h3>Time-Locked Savings</h3>
<p>Lock your ETH for a specific duration</p>
</div>
</ErrorBoundary>
<ErrorBoundary level="component">
<div className="feature">
<span className="icon">💰</span>
<h3>Secure Storage</h3>
<p>Your funds are safe on-chain</p>
</div>
</ErrorBoundary>
<ErrorBoundary level="component">
<div className="feature">
<span className="icon">⚡</span>
<h3>Base Network</h3>
<p>Fast and low-cost transactions</p>
</div>
</ErrorBoundary>
</div>
<div className="connect-action">
<p>Connect your wallet to get started</p>
<appkit-button />
</div>
</div>
</div>
</ErrorBoundary>
) : currentPage === 'admin' ? (
<ErrorBoundary level="page">
<AdminDashboard />
</ErrorBoundary>
) : currentPage === 'debug' ? (
<ErrorBoundary level="page">
<DebugPage />
</ErrorBoundary>
) : (
<ErrorBoundary level="page">
<PiggyBankDashboard />
</ErrorBoundary>
)}
</main>

<footer className="footer">
<ErrorBoundary level="component">
<p>Built with REOWN AppKit & WalletConnect on Base</p>
</ErrorBoundary>
</footer>
</div>
</NotificationProvider>
</ErrorBoundary>
)
}

export default App
150 changes: 0 additions & 150 deletions frontend/src/index.css
Original file line number Diff line number Diff line change
@@ -1,150 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
line-height: 1.6;
font-weight: 400;

--primary: #7c3aed;
--primary-dark: #6d28d9;
--primary-light: #8b5cf6;
--secondary: #0052ff;
--success: #10b981;
--warning: #f59e0b;
--error: #ef4444;
--bg-primary: #0a0a0f;
--bg-secondary: #16161f;
--bg-card: #1e1e2e;
--text-primary: #ffffff;
--text-secondary: #a1a1aa;
--border: #2d2d3a;

font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
margin: 0;
min-width: 320px;
min-height: 100vh;
background: linear-gradient(135deg, #0a0a0f 0%, #1a0b2e 100%);
color: var(--text-primary);
}

#root {
width: 100%;
min-height: 100vh;
}

a {
font-weight: 500;
color: var(--primary);
text-decoration: none;
transition: color 0.2s;
}

a:hover {
color: var(--primary-light);
}

button {
cursor: pointer;
font-family: inherit;
}

input,
select,
textarea {
font-family: inherit;
font-size: inherit;
}

/* Scrollbar styling */
::-webkit-scrollbar {
width: 10px;
}

::-webkit-scrollbar-track {
background: var(--bg-secondary);
}

::-webkit-scrollbar-thumb {
background: var(--primary);
border-radius: 5px;
}

::-webkit-scrollbar-thumb:hover {
background: var(--primary-dark);
}

/* Mobile-first responsive utilities */
@media (max-width: 360px) {
html {
font-size: 14px;
}
}

@media (min-width: 361px) and (max-width: 414px) {
html {
font-size: 15px;
}
}

@media (min-width: 415px) and (max-width: 768px) {
html {
font-size: 16px;
}
}

/* Prevent horizontal scrolling on mobile */
body {
overflow-x: hidden;
}

/* Improve touch targets on mobile */
@media (max-width: 768px) {
button,
.btn,
.nav-btn,
.tab,
.network-btn,
.network-option,
.copy-btn {
min-height: 44px; /* Apple's recommended minimum touch target */
min-width: 44px;
}

/* Increase spacing between interactive elements */
button + button,
.btn + .btn,
.nav-btn + .nav-btn {
margin-top: 0.5rem;
}
}

/* Prevent text size adjustment on mobile */
@media (max-width: 768px) {
* {
-webkit-text-size-adjust: 100%;
-moz-text-size-adjust: 100%;
text-size-adjust: 100%;
}
}

/* Smooth scrolling on mobile */
@media (max-width: 768px) {
html {
scroll-behavior: smooth;
}
}
19 changes: 0 additions & 19 deletions frontend/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +0,0 @@
import React, { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { WagmiProvider } from 'wagmi' // cspell:ignore wagmi
import { QueryClientProvider } from '@tanstack/react-query'
import { App } from './App'
import { wagmiConfig, queryClient } from './config/wagmi'

const container = document.getElementById('root')!
const root = createRoot(container)

root.render(
<StrictMode>
<QueryClientProvider client={queryClient}>
<WagmiProvider config={wagmiConfig}>
<App />
</WagmiProvider>
</QueryClientProvider>
</StrictMode>,
)
Loading