Auto commit: 2026-01-03T08:58:39.154Z
This commit is contained in:
parent
7dde39bcd5
commit
5d42eee08c
BIN
assets/pasted-20260103-085152-d00111a6.png
Normal file
BIN
assets/pasted-20260103-085152-d00111a6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 191 KiB |
BIN
assets/vm-shot-2026-01-03T08-49-54-364Z.jpg
Normal file
BIN
assets/vm-shot-2026-01-03T08-49-54-364Z.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
@ -1,79 +1,318 @@
|
||||
:root {
|
||||
--primary-color: #4F46E5;
|
||||
--sidebar-bg: #111827;
|
||||
--sidebar-text: #9CA3AF;
|
||||
--sidebar-active-bg: #374151;
|
||||
--sidebar-active-text: #FFFFFF;
|
||||
--main-bg: #F9FAFB;
|
||||
--text-primary: #1F2937;
|
||||
--text-secondary: #6B7280;
|
||||
--card-bg: #FFFFFF;
|
||||
--border-color: #E5E7EB;
|
||||
--green-light: #ECFDF5;
|
||||
--green-dark: #065F46;
|
||||
--red-light: #FEF2F2;
|
||||
--red-dark: #991B1B;
|
||||
--blue-light: #EFF6FF;
|
||||
--blue-dark: #1E40AF;
|
||||
--yellow-light: #FFFBEB;
|
||||
--yellow-dark: #92400E;
|
||||
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background-color: var(--main-bg);
|
||||
color: var(--text-primary);
|
||||
margin: 0;
|
||||
background-color: #f4f7fa;
|
||||
color: #333;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.dashboard {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 240px;
|
||||
background-color: #fff;
|
||||
border-right: 1px solid #e0e0e0;
|
||||
padding: 20px;
|
||||
width: 260px;
|
||||
background-color: var(--sidebar-bg);
|
||||
color: var(--sidebar-text);
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 20px;
|
||||
.sidebar-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.sidebar ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
.sidebar-logo {
|
||||
background-color: var(--primary-color);
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.sidebar li a {
|
||||
display: block;
|
||||
padding: 10px 15px;
|
||||
.sidebar-school-name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sidebar-school-name span:first-child {
|
||||
font-weight: 600;
|
||||
color: var(--sidebar-active-text);
|
||||
}
|
||||
|
||||
.sidebar-school-name span:last-child {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.nav-section {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.nav-section-title {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 12px;
|
||||
border-radius: 6px;
|
||||
text-decoration: none;
|
||||
color: #555;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 5px;
|
||||
color: var(--sidebar-text);
|
||||
font-weight: 500;
|
||||
margin-bottom: 4px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.sidebar li a:hover, .sidebar li a.active {
|
||||
background-color: #eef2f5;
|
||||
color: #007bff;
|
||||
.nav-item:hover {
|
||||
background-color: #1F2937;
|
||||
color: var(--sidebar-active-text);
|
||||
}
|
||||
|
||||
.nav-item.active {
|
||||
background-color: var(--sidebar-active-bg);
|
||||
color: var(--sidebar-active-text);
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
padding: 24px 32px;
|
||||
background-color: var(--card-bg);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
.search-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.search-bar input {
|
||||
width: 100%;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 6px;
|
||||
padding: 10px 14px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.user-info span {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.user-info span:first-child {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.user-info span:last-child {
|
||||
font-size: 0.875rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.page-content {
|
||||
padding: 32px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.welcome-header {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.welcome-header h1 {
|
||||
font-size: 1.875rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 4px 0;
|
||||
}
|
||||
|
||||
.welcome-header p {
|
||||
font-size: 1rem;
|
||||
color: var(--text-secondary);
|
||||
margin: 0;
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 24px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
margin-top: 0;
|
||||
.stat-card {
|
||||
background-color: var(--card-bg);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
border: 1px solid var(--border-color);
|
||||
box-shadow: 0 1px 3px 0 rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.stat-card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.stat-card-title {
|
||||
font-weight: 500;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.stat-card-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.stat-card-icon.blue { background-color: var(--blue-light); color: var(--blue-dark); }
|
||||
.stat-card-icon.green { background-color: var(--green-light); color: var(--green-dark); }
|
||||
.stat-card-icon.red { background-color: var(--red-light); color: var(--red-dark); }
|
||||
|
||||
.stat-card-value {
|
||||
font-size: 2.25rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.stat-card-footer {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.stat-card-footer .increase { color: var(--green-dark); }
|
||||
.stat-card-footer .decrease { color: var(--red-dark); }
|
||||
|
||||
.charts-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 24px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.chart-card {
|
||||
background-color: var(--card-bg);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
border: 1px solid var(--border-color);
|
||||
box-shadow: 0 1px 3px 0 rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.chart-card-header h3 {
|
||||
margin: 0 0 4px 0;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.chart-card-header p {
|
||||
margin: 0;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.chart-placeholder {
|
||||
height: 250px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.table-card {
|
||||
background-color: var(--card-bg);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
border: 1px solid var(--border-color);
|
||||
box-shadow: 0 1px 3px 0 rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.table-card h3 {
|
||||
margin: 0 0 16px 0;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 12px 16px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
thead th {
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
@ -3,18 +3,23 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>School Accounting Dashboard</title>
|
||||
<link rel="stylesheet" href="dashboard/assets/css/style.css">
|
||||
<!-- React and Babel for JSX transpilation -->
|
||||
<title>Mother Providencia International School</title>
|
||||
<link rel="stylesheet" href="assets/css/style.css">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<script src="https://unpkg.com/feather-icons"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
|
||||
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
<!-- React Application -->
|
||||
<script type="text/babel" src="dashboard/src/App.js"></script>
|
||||
<script type="text/babel" src="dashboard/src/index.js"></script>
|
||||
<script type="text/babel" src="src/App.js"></script>
|
||||
<script type="text/babel" src="src/index.js"></script>
|
||||
<script>
|
||||
feather.replace();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,74 +1,265 @@
|
||||
const App = () => {
|
||||
// State to hold trial balance data
|
||||
const [trialBalance, setTrialBalance] = React.useState(null);
|
||||
const [error, setError] = React.useState(null);
|
||||
|
||||
const App = () => {
|
||||
React.useEffect(() => {
|
||||
// Fetch trial balance data
|
||||
fetch('/api/reports/trial_balance.php')
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
feather.replace();
|
||||
|
||||
// Mock Chart for Income vs Expenses
|
||||
const incomeExpenseCtx = document.getElementById('incomeExpenseChart');
|
||||
if (incomeExpenseCtx) {
|
||||
new Chart(incomeExpenseCtx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ['Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb'],
|
||||
datasets: [{
|
||||
label: 'Income',
|
||||
data: [120000, 130000, 140000, 135000, 150000, 160000],
|
||||
borderColor: '#10B981',
|
||||
backgroundColor: 'rgba(16, 185, 129, 0.1)',
|
||||
fill: true,
|
||||
tension: 0.4
|
||||
}, {
|
||||
label: 'Expenses',
|
||||
data: [90000, 95000, 105000, 100000, 110000, 115000],
|
||||
borderColor: '#EF4444',
|
||||
backgroundColor: 'rgba(239, 68, 68, 0.1)',
|
||||
fill: true,
|
||||
tension: 0.4
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
callback: function(value) {
|
||||
return '$' + value / 1000 + 'k';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
setTrialBalance(data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error fetching trial balance:", error);
|
||||
setError(error.toString());
|
||||
});
|
||||
}
|
||||
|
||||
// Mock Chart for Fee Collection
|
||||
const feeCollectionCtx = document.getElementById('feeCollectionChart');
|
||||
if (feeCollectionCtx) {
|
||||
new Chart(feeCollectionCtx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: ['Collected', 'Pending', 'Overdue'],
|
||||
datasets: [{
|
||||
data: [85, 10, 5],
|
||||
backgroundColor: ['#10B981', '#F59E0B', '#EF4444'],
|
||||
borderWidth: 0
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
cutout: '70%',
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
const navItems = {
|
||||
Overview: [
|
||||
{ name: 'Dashboard', icon: 'grid', active: true },
|
||||
],
|
||||
Academic: [
|
||||
{ name: 'Students', icon: 'users' },
|
||||
{ name: 'Teachers', icon: 'users' },
|
||||
{ name: 'Classes', icon: 'book' },
|
||||
{ name: 'Timetable', icon: 'calendar' },
|
||||
{ name: 'Attendance', icon: 'check-square' },
|
||||
{ name: 'Examinations', icon: 'file-text' },
|
||||
],
|
||||
Finance: [
|
||||
{ name: 'Chart of Accounts', icon: 'file' },
|
||||
{ name: 'Journal Entries', icon: 'book-open' },
|
||||
{ name: 'Invoices (AR)', icon: 'dollar-sign' },
|
||||
{ name: 'Payments', icon: 'trending-up' },
|
||||
{ name: 'Bills (AP)', icon: 'file-minus' },
|
||||
{ name: 'Vendors', icon: 'briefcase' },
|
||||
{ name: 'Inventory', icon: 'archive' },
|
||||
]
|
||||
};
|
||||
|
||||
const stats = [
|
||||
{ title: 'Total Students', value: '487', change: '+12 this month', changeType: 'increase', icon: 'users', iconBg: 'blue' },
|
||||
{ title: 'Total Teachers', value: '32', change: '2 on leave', icon: 'users', iconBg: 'blue' },
|
||||
{ title: 'Total Revenue', value: 'GH₵1,085,500.00', change: '+8.2% from last year', changeType: 'increase', icon: 'dollar-sign', iconBg: 'green' },
|
||||
{ title: 'Pending Fees', value: 'GH₵85,000.00', change: '12 invoices overdue', changeType: 'decrease', icon: 'alert-triangle', iconBg: 'red' },
|
||||
];
|
||||
|
||||
const Sidebar = () => (
|
||||
<div className="sidebar">
|
||||
<div className="sidebar-header">
|
||||
<div className="sidebar-logo">
|
||||
<i data-feather="award"></i>
|
||||
</div>
|
||||
<div className="sidebar-school-name">
|
||||
<span>Mother Providencia</span>
|
||||
<span>International School</span>
|
||||
</div>
|
||||
</div>
|
||||
<nav>
|
||||
{Object.entries(navItems).map(([section, items]) => (
|
||||
<div className="nav-section" key={section}>
|
||||
<div className="nav-section-title">{section}</div>
|
||||
{items.map(item => (
|
||||
<a href="#" className={`nav-item ${item.active ? 'active' : ''}`} key={item.name}>
|
||||
<i data-feather={item.icon}></i>
|
||||
<span>{item.name}</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
<div style={{ marginTop: 'auto' }}>
|
||||
<a href="#" className="nav-item">
|
||||
<i data-feather="settings"></i>
|
||||
<span>Settings</span>
|
||||
</a>
|
||||
<a href="#" className="nav-item">
|
||||
<i data-feather="log-out"></i>
|
||||
<span>Logout</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const Header = () => (
|
||||
<header className="header">
|
||||
<div className="search-bar">
|
||||
<i data-feather="search" style={{ color: 'var(--text-secondary)' }}></i>
|
||||
<input type="text" placeholder="Search students, invoices, accounts..." />
|
||||
</div>
|
||||
<div className="header-actions">
|
||||
<button className="admin-btn" style={{background: '#f8d7da', border: 'none', padding: '5px 10px', borderRadius: '5px'}}>admin</button>
|
||||
<span>Switch Role</span>
|
||||
<i data-feather="bell"></i>
|
||||
<div className="user-profile">
|
||||
<div className="user-avatar">JA</div>
|
||||
<div className="user-info">
|
||||
<span>John Administrator</span>
|
||||
<span>Admin</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
||||
const StatCard = ({ stat }) => (
|
||||
<div className="stat-card">
|
||||
<div className="stat-card-header">
|
||||
<span className="stat-card-title">{stat.title}</span>
|
||||
<div className={`stat-card-icon ${stat.iconBg}`}>
|
||||
<i data-feather={stat.icon}></i>
|
||||
</div>
|
||||
</div>
|
||||
<div className="stat-card-value">{stat.value}</div>
|
||||
<div className={`stat-card-footer ${stat.changeType}`}>{stat.change}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="dashboard">
|
||||
<aside className="sidebar">
|
||||
<h2>Dashboard</h2>
|
||||
<ul>
|
||||
<li><a href="#" className="active">Overview</a></li>
|
||||
<li><a href="#">Reports</a></li>
|
||||
<li><a href="#">Students</a></li>
|
||||
<li><a href="#">Invoices</a></li>
|
||||
<li><a href="#">Payments</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<Sidebar />
|
||||
<main className="main-content">
|
||||
<header className="header">
|
||||
<h1>Financial Overview</h1>
|
||||
</header>
|
||||
<div className="card">
|
||||
<h3>Trial Balance</h3>
|
||||
{error && <p>Error loading data: {error}</p>}
|
||||
{!trialBalance && !error && <p>Loading...</p>}
|
||||
{trialBalance && (
|
||||
<Header />
|
||||
<div className="page-content">
|
||||
<div className="welcome-header">
|
||||
<h1>Welcome back, John!</h1>
|
||||
<p>Here's your administrative overview of the school.</p>
|
||||
</div>
|
||||
<div className="stats-grid">
|
||||
{stats.map(stat => <StatCard stat={stat} key={stat.title} />)}
|
||||
</div>
|
||||
<div className="charts-grid">
|
||||
<div className="chart-card">
|
||||
<div className="chart-card-header">
|
||||
<h3>Cash Position</h3>
|
||||
<p>Current balances</p>
|
||||
</div>
|
||||
<div style={{height: '250px', display:'flex', flexDirection: 'column', justifyContent:'center', gap: '20px'}}>
|
||||
<div style={{display: 'flex', alignItems: 'center', gap: '15px'}}>
|
||||
<div style={{padding: '10px', background: 'var(--blue-light)', borderRadius: '8px'}}><i data-feather="briefcase"></i></div>
|
||||
<div>
|
||||
<div>Bank Account</div>
|
||||
<div style={{fontSize: '1.5rem', fontWeight: '600'}}>GH₵650,000.00</div>
|
||||
<div style={{fontSize: '0.8rem', color: 'var(--text-secondary)'}}>Operating + Savings</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{display: 'flex', alignItems: 'center', gap: '15px'}}>
|
||||
<div style={{padding: '10px', background: 'var(--green-light)', borderRadius: '8px'}}><i data-feather="dollar-sign"></i></div>
|
||||
<div>
|
||||
<div>Petty Cash</div>
|
||||
<div style={{fontSize: '1.5rem', fontWeight: '600'}}>GH₵2,500.00</div>
|
||||
<div style={{fontSize: '0.8rem', color: 'var(--text-secondary)'}}>On hand</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{color: 'var(--red-dark)', fontWeight:'500', display:'flex', alignItems:'center', gap: '5px'}}><i data-feather="trending-down"></i>Upcoming payables GH₵31,000.00</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="chart-card">
|
||||
<div className="chart-card-header">
|
||||
<h3>Fee Collection</h3>
|
||||
<p>Current academic year</p>
|
||||
</div>
|
||||
<div className="chart-placeholder">
|
||||
<canvas id="feeCollectionChart"></canvas>
|
||||
</div>
|
||||
<div style={{display: 'flex', justifyContent: 'center', gap: '15px', marginTop: '15px'}}>
|
||||
<span style={{display:'flex', alignItems: 'center', gap: '5px'}}><div style={{width:'10px', height: '10px', borderRadius: '50%', background: '#10B981'}}></div>Collected</span>
|
||||
<span style={{display:'flex', alignItems: 'center', gap: '5px'}}><div style={{width:'10px', height: '10px', borderRadius: '50%', background: '#F59E0B'}}></div>Pending</span>
|
||||
<span style={{display:'flex', alignItems: 'center', gap: '5px'}}><div style={{width:'10px', height: '10px', borderRadius: '50%', background: '#EF4444'}}></div>Overdue</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="chart-card">
|
||||
<div className="chart-card-header">
|
||||
<h3>Income vs Expenses</h3>
|
||||
<p>Last 6 months trend</p>
|
||||
</div>
|
||||
<div className="chart-placeholder">
|
||||
<canvas id="incomeExpenseChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="charts-grid" style={{gridTemplateColumns: '1fr 1fr'}}>
|
||||
<div className="table-card">
|
||||
<h3>Recent Invoices</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Account</th>
|
||||
<th>Debit</th>
|
||||
<th>Credit</th>
|
||||
</tr>
|
||||
<tr><th>Student</th><th>Amount</th><th>Status</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{trialBalance.lines.map((line, index) => (
|
||||
<tr key={index}>
|
||||
<td>{line.account_name}</td>
|
||||
<td>{line.debit}</td>
|
||||
<td>{line.credit}</td>
|
||||
</tr>
|
||||
))}
|
||||
<tr>
|
||||
<td><b>{trialBalance.totals.account_name}</b></td>
|
||||
<td><b>{trialBalance.totals.debit}</b></td>
|
||||
<td><b>{trialBalance.totals.credit}</b></td>
|
||||
</tr>
|
||||
<tr><td>Kwabena Adu</td><td>GH₵1,200.00</td><td>Paid</td></tr>
|
||||
<tr><td>Afiya Owusu</td><td>GH₵1,200.00</td><td>Pending</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
</div>
|
||||
<div className="table-card">
|
||||
<h3>Recent Payments</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>Student</th><th>Amount</th><th>Date</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>Kwabena Adu</td><td>GH₵1,200.00</td><td>2024-02-15</td></tr>
|
||||
<tr><td>Esi Mensah</td><td>GH₵1,000.00</td><td>2024-02-14</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user