From fda5370844f0055183c5fa191841aeca17ba534c Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Thu, 22 Jan 2026 15:00:20 +0000 Subject: [PATCH] V1 --- assets/css/custom.css | 469 +++++++++++----------------- assets/js/main.js | 113 +++---- db/config.php | 6 +- db/migrations/01_initial_schema.sql | 28 ++ index.php | 324 ++++++++++--------- 5 files changed, 435 insertions(+), 505 deletions(-) create mode 100644 db/migrations/01_initial_schema.sql diff --git a/assets/css/custom.css b/assets/css/custom.css index 65a1626..d41dc27 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -1,346 +1,229 @@ :root { - --color-bg: #ffffff; - --color-text: #1a1a1a; - --color-primary: #2563EB; /* Vibrant Blue */ - --color-secondary: #000000; - --color-accent: #A3E635; /* Lime Green */ - --color-surface: #f8f9fa; - --font-heading: 'Space Grotesk', sans-serif; - --font-body: 'Inter', sans-serif; - --border-width: 2px; - --shadow-hard: 5px 5px 0px #000; - --shadow-hover: 8px 8px 0px #000; - --radius-pill: 50rem; - --radius-card: 1rem; + --primary-green: #059669; + --primary-blue: #1E3A8A; + --accent-gold: #D4AF37; + --bg-light: #F9FAFB; + --text-dark: #111827; + --text-muted: #6B7280; + --card-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); } body { - font-family: var(--font-body); - background-color: var(--color-bg); - color: var(--color-text); - overflow-x: hidden; + background-color: var(--bg-light); + font-family: 'Inter', system-ui, -apple-system, sans-serif; + color: var(--text-dark); + padding-bottom: 2rem; } -h1, h2, h3, h4, h5, h6, .navbar-brand { - font-family: var(--font-heading); - letter-spacing: -0.03em; -} - -/* Utilities */ -.text-primary { color: var(--color-primary) !important; } -.bg-black { background-color: #000 !important; } -.text-white { color: #fff !important; } -.shadow-hard { box-shadow: var(--shadow-hard); } -.border-2-black { border: var(--border-width) solid #000; } -.py-section { padding-top: 5rem; padding-bottom: 5rem; } - -/* Navbar */ .navbar { - background: rgba(255, 255, 255, 0.9); - backdrop-filter: blur(10px); - border-bottom: var(--border-width) solid transparent; - transition: all 0.3s; - padding-top: 1rem; - padding-bottom: 1rem; + background: white; + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1); + padding: 0.75rem 1rem; } -.navbar.scrolled { - border-bottom-color: #000; - padding-top: 0.5rem; - padding-bottom: 0.5rem; +.navbar-brand { + font-weight: 700; + color: var(--primary-blue); + display: flex; + align-items: center; + gap: 0.5rem; } -.brand-text { +.navbar-brand span { + color: var(--primary-green); +} + +.currency-badge { + background: #E5E7EB; + border-radius: 9999px; + padding: 0.25rem 0.75rem; + font-size: 0.875rem; + font-weight: 600; + cursor: pointer; + transition: background 0.2s; +} + +.currency-badge:hover { + background: #D1D5DB; +} + +/* Wallet Cards Slider */ +.wallet-slider { + display: flex; + overflow-x: auto; + gap: 1rem; + padding: 1rem 0; + scrollbar-width: none; /* Firefox */ +} + +.wallet-slider::-webkit-scrollbar { + display: none; /* Safari and Chrome */ +} + +.wallet-card { + min-width: 280px; + background: white; + border-radius: 12px; + padding: 1.25rem; + box-shadow: var(--card-shadow); + border-left: 4px solid var(--primary-blue); + transition: transform 0.2s; +} + +.wallet-card:active { + transform: scale(0.98); +} + +.wallet-card.tontine { border-left-color: var(--accent-gold); } +.wallet-card.savings { border-left-color: var(--primary-green); } + +.wallet-type { + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--text-muted); + margin-bottom: 0.5rem; + font-weight: 600; +} + +.wallet-balance { font-size: 1.5rem; - font-weight: 800; -} - -.nav-link { - font-weight: 500; - color: var(--color-text); - margin-left: 1rem; - position: relative; -} - -.nav-link:hover, .nav-link.active { - color: var(--color-primary); -} - -/* Buttons */ -.btn { font-weight: 700; - font-family: var(--font-heading); - padding: 0.8rem 2rem; - border-radius: var(--radius-pill); - border: var(--border-width) solid #000; - transition: all 0.2s cubic-bezier(0.25, 1, 0.5, 1); - box-shadow: var(--shadow-hard); + color: var(--text-dark); } -.btn:hover { - transform: translate(-2px, -2px); - box-shadow: var(--shadow-hover); +.wallet-currency { + font-size: 0.875rem; + color: var(--text-muted); + margin-left: 0.25rem; } -.btn:active { - transform: translate(2px, 2px); - box-shadow: 0 0 0 #000; +/* Quick Actions */ +.action-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 0.75rem; + margin-top: 1.5rem; } -.btn-primary { - background-color: var(--color-primary); - border-color: #000; - color: #fff; -} - -.btn-primary:hover { - background-color: #1d4ed8; - border-color: #000; - color: #fff; -} - -.btn-outline-dark { - background-color: #fff; - color: #000; -} - -.btn-cta { - background-color: var(--color-accent); - color: #000; -} - -.btn-cta:hover { - background-color: #8cc629; - color: #000; -} - -/* Hero Section */ -.hero-section { - min-height: 100vh; - padding-top: 80px; -} - -.background-blob { - position: absolute; - border-radius: 50%; - filter: blur(80px); - opacity: 0.6; - z-index: 1; -} - -.blob-1 { - top: -10%; - right: -10%; - width: 600px; - height: 600px; - background: radial-gradient(circle, var(--color-accent), transparent); -} - -.blob-2 { - bottom: 10%; - left: -10%; - width: 500px; - height: 500px; - background: radial-gradient(circle, var(--color-primary), transparent); -} - -.highlight-text { - background: linear-gradient(120deg, transparent 0%, transparent 40%, var(--color-accent) 40%, var(--color-accent) 100%); - background-repeat: no-repeat; - background-size: 100% 40%; - background-position: 0 88%; - padding: 0 5px; -} - -.dot { color: var(--color-primary); } - -.badge-pill { - display: inline-block; - padding: 0.5rem 1rem; - border: 2px solid #000; - border-radius: 50px; - font-weight: 700; - background: #fff; - box-shadow: 4px 4px 0 #000; - font-family: var(--font-heading); - font-size: 0.9rem; -} - -/* Marquee */ -.marquee-container { - overflow: hidden; - white-space: nowrap; - border-top: 2px solid #000; - border-bottom: 2px solid #000; -} - -.rotate-divider { - transform: rotate(-2deg) scale(1.05); - z-index: 10; - position: relative; - margin-top: -50px; - margin-bottom: 30px; -} - -.marquee-content { - display: inline-block; - animation: marquee 20s linear infinite; - font-family: var(--font-heading); - font-weight: 700; - font-size: 1.5rem; - letter-spacing: 2px; -} - -@keyframes marquee { - 0% { transform: translateX(0); } - 100% { transform: translateX(-50%); } -} - -/* Portfolio Cards */ -.project-card { - border: 2px solid #000; - border-radius: var(--radius-card); - overflow: hidden; - background: #fff; - transition: transform 0.3s ease; - box-shadow: var(--shadow-hard); - height: 100%; +.action-btn { display: flex; flex-direction: column; + align-items: center; + gap: 0.5rem; + background: white; + border: none; + border-radius: 12px; + padding: 1rem 0.5rem; + box-shadow: var(--card-shadow); + transition: background 0.2s; } -.project-card:hover { - transform: translateY(-10px); - box-shadow: 8px 8px 0 #000; +.action-btn:active { + background: #F3F4F6; } -.card-img-holder { - height: 250px; +.action-icon { + width: 40px; + height: 40px; + border-radius: 10px; display: flex; align-items: center; justify-content: center; - border-bottom: 2px solid #000; - position: relative; - font-size: 4rem; + background: #EFF6FF; + color: var(--primary-blue); } -.placeholder-art { - transition: transform 0.3s ease; +.action-btn.tontine .action-icon { + background: #FEF3C7; + color: #B45309; } -.project-card:hover .placeholder-art { - transform: scale(1.2) rotate(10deg); +.action-label { + font-size: 0.7rem; + font-weight: 600; + color: var(--text-dark); + text-align: center; } -.bg-soft-blue { background-color: #e0f2fe; } -.bg-soft-green { background-color: #dcfce7; } -.bg-soft-purple { background-color: #f3e8ff; } -.bg-soft-yellow { background-color: #fef9c3; } - -.category-tag { - position: absolute; - top: 15px; - right: 15px; - background: #000; - color: #fff; - padding: 5px 12px; - border-radius: 20px; - font-size: 0.75rem; - font-weight: 700; +/* Activity List */ +.activity-section { + margin-top: 2rem; } -.card-body { padding: 1.5rem; } - -.link-arrow { - text-decoration: none; - color: #000; - font-weight: 700; - display: inline-flex; +.section-header { + display: flex; + justify-content: space-between; align-items: center; - margin-top: auto; + margin-bottom: 1rem; } -.link-arrow i { transition: transform 0.2s; margin-left: 5px; } -.link-arrow:hover i { transform: translateX(5px); } - -/* About */ -.about-image-stack { - position: relative; - height: 400px; - width: 100%; +.section-title { + font-size: 1.125rem; + font-weight: 700; } -.stack-card { - position: absolute; - width: 80%; - height: 100%; - border-radius: var(--radius-card); - border: 2px solid #000; - box-shadow: var(--shadow-hard); - left: 10%; - transform: rotate(-3deg); - background-size: cover; -} - -/* Forms */ -.form-control { - border: 2px solid #000; - border-radius: 0.5rem; +.activity-item { + background: white; + border-radius: 12px; padding: 1rem; - font-weight: 500; - background: #f8f9fa; + display: flex; + align-items: center; + gap: 1rem; + margin-bottom: 0.75rem; + box-shadow: var(--card-shadow); } -.form-control:focus { - box-shadow: 4px 4px 0 var(--color-primary); - border-color: #000; - background: #fff; +.activity-icon { + width: 40px; + height: 40px; + border-radius: 50%; + background: #F3F4F6; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; } -/* Animations */ -.animate-up { - opacity: 0; - transform: translateY(30px); - animation: fadeUp 0.8s ease forwards; +.activity-details { + flex-grow: 1; } -.delay-100 { animation-delay: 0.1s; } -.delay-200 { animation-delay: 0.2s; } - -@keyframes fadeUp { - to { - opacity: 1; - transform: translateY(0); - } +.activity-name { + font-weight: 600; + font-size: 0.9rem; } -/* Social */ -.social-links a { - transition: transform 0.2s; - display: inline-block; -} -.social-links a:hover { - transform: scale(1.2) rotate(10deg); - color: var(--color-accent) !important; +.activity-meta { + font-size: 0.75rem; + color: var(--text-muted); } -/* Responsive */ -@media (max-width: 991px) { - .rotate-divider { - transform: rotate(0); - margin-top: 0; - margin-bottom: 2rem; - } - - .hero-section { - padding-top: 120px; - text-align: center; - min-height: auto; - padding-bottom: 100px; - } - - .display-1 { font-size: 3.5rem; } - - .blob-1 { width: 300px; height: 300px; right: -20%; } - .blob-2 { width: 300px; height: 300px; left: -20%; } +.activity-amount { + font-weight: 700; + text-align: right; } + +.amount-positive { color: var(--primary-green); } +.amount-negative { color: #DC2626; } + +.status-badge { + font-size: 0.65rem; + padding: 0.1rem 0.4rem; + border-radius: 4px; + text-transform: uppercase; + font-weight: 700; +} + +.status-pending { background: #FEF3C7; color: #92400E; } +.status-success { background: #D1FAE5; color: #065F46; } + +/* Modal Styles */ +.modal-content { + border-radius: 16px; + border: none; +} + +.modal-header { + border-bottom: 1px solid #F3F4F6; +} \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js index fdf2cfd..1b9b332 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,73 +1,52 @@ document.addEventListener('DOMContentLoaded', () => { - - // Smooth scrolling for navigation links - document.querySelectorAll('a[href^="#"]').forEach(anchor => { - anchor.addEventListener('click', function (e) { - e.preventDefault(); - const targetId = this.getAttribute('href'); - if (targetId === '#') return; - - const targetElement = document.querySelector(targetId); - if (targetElement) { - // Close mobile menu if open - const navbarToggler = document.querySelector('.navbar-toggler'); - const navbarCollapse = document.querySelector('.navbar-collapse'); - if (navbarCollapse.classList.contains('show')) { - navbarToggler.click(); - } - - // Scroll with offset - const offset = 80; - const elementPosition = targetElement.getBoundingClientRect().top; - const offsetPosition = elementPosition + window.pageYOffset - offset; - - window.scrollTo({ - top: offsetPosition, - behavior: "smooth" - }); - } - }); - }); - - // Navbar scroll effect - const navbar = document.querySelector('.navbar'); - window.addEventListener('scroll', () => { - if (window.scrollY > 50) { - navbar.classList.add('scrolled', 'shadow-sm', 'bg-white'); - navbar.classList.remove('bg-transparent'); - } else { - navbar.classList.remove('scrolled', 'shadow-sm', 'bg-white'); - navbar.classList.add('bg-transparent'); - } - }); - - // Intersection Observer for fade-up animations - const observerOptions = { - threshold: 0.1, - rootMargin: "0px 0px -50px 0px" + const exchangeRates = { + 'XOF': 1, + 'GHS': 0.02, // Mock: 1 XOF = 0.02 GHS (fake) + 'GNF': 13.5 // Mock: 1 XOF = 13.5 GNF (fake) }; - const observer = new IntersectionObserver((entries) => { - entries.forEach(entry => { - if (entry.isIntersecting) { - entry.target.classList.add('animate-up'); - entry.target.style.opacity = "1"; - observer.unobserve(entry.target); // Only animate once - } - }); - }, observerOptions); + const currencySymbols = { + 'XOF': 'CFA', + 'GHS': 'GH₵', + 'GNF': 'FG' + }; - // Select elements to animate (add a class 'reveal' to them in HTML if not already handled by CSS animation) - // For now, let's just make sure the hero animations run. - // If we want scroll animations, we'd add opacity: 0 to elements in CSS and reveal them here. - // Given the request, the CSS animation I added runs on load for Hero. - // Let's make the project cards animate in. - - const projectCards = document.querySelectorAll('.project-card'); - projectCards.forEach((card, index) => { - card.style.opacity = "0"; - card.style.animationDelay = `${index * 0.1}s`; - observer.observe(card); + let currentCurrency = 'XOF'; + + const currencyBadge = document.getElementById('currencyBadge'); + const balanceElements = document.querySelectorAll('[data-base-balance]'); + + function updateBalances(newCurrency) { + currentCurrency = newCurrency; + currencyBadge.textContent = newCurrency; + + balanceElements.forEach(el => { + const baseBalance = parseFloat(el.getAttribute('data-base-balance')); + const converted = baseBalance * exchangeRates[newCurrency]; + + // Formatting + let formatted; + if (newCurrency === 'XOF') { + formatted = new Intl.NumberFormat('fr-FR').format(Math.round(converted)); + } else { + formatted = new Intl.NumberFormat('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(converted); + } + + el.innerHTML = `${formatted} ${currencySymbols[newCurrency]}`; + }); + } + + currencyBadge.addEventListener('click', () => { + const currencies = ['XOF', 'GHS', 'GNF']; + let nextIndex = (currencies.indexOf(currentCurrency) + 1) % currencies.length; + updateBalances(currencies[nextIndex]); }); -}); \ No newline at end of file + // Mock Quick Actions + document.querySelectorAll('.action-btn').forEach(btn => { + btn.addEventListener('click', () => { + const action = btn.querySelector('.action-label').textContent; + alert(`${action} module coming soon!`); + }); + }); +}); diff --git a/db/config.php b/db/config.php index 9a2eebd..514bcf0 100644 --- a/db/config.php +++ b/db/config.php @@ -1,8 +1,8 @@ - - - - - - New Style -prepare("SELECT * FROM users WHERE id = 1"); + $stmt->execute(); + $user = $stmt->fetch(); + + $stmt = db()->prepare("SELECT * FROM wallets WHERE user_id = 1"); + $stmt->execute(); + $wallets = $stmt->fetchAll(); + + // Index wallets by type for easy access + $walletMap = []; + foreach ($wallets as $w) { + $walletMap[$w['type']] = $w; + } +} catch (Exception $e) { + die("Error connecting to database: " . $e->getMessage()); +} + +$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'AfriPay-Tontine: Comprehensive financial services for West Africa.'; $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; ?> - - - - - - - - - - - - - - - - - - + + + + + + AfriPay-Tontine | Dashboard + + + + + + + + + + + + + + + + -
-
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

+ + + + +
+ +
+
Hello, 👋
+

Your financial overview in

+
+ + +
+ +
+
Current Account
+
+ CFA +
+
Available Balance
+
+ + +
+
Savings
+
+ CFA +
+
+2.5% p.a.
+
+ + +
+
Tontine Pot
+
+ CFA +
+
3 active groups
+
+ + +
+
Escrow (SafePay)
+
+ CFA +
+
Funds locked for delivery
+
+
+ + +
+ + + + +
+ + +
+
+
Recent Activity
+ See all +
+ +
+
+
+
MTN Mobile Money
+
Today, 10:45 AM • Deposit
+
+
+
+15 000
+ Success +
+
+ +
+
+
+
Ghana Tontine 🇬🇭
+
Yesterday • Contribution
+
+
+
-50 000
+ Pending +
+
+
-
- + + +
+
+ + Home +
+
+ + Wallets +
+
+ + Tontine +
+
+ + Settings +
+
+ + + + - + \ No newline at end of file