Fixed a bunch of stuff

This commit is contained in:
Mitchell Magro 2025-06-29 08:49:58 +02:00
parent 26e97a0c44
commit c4692e2222
18 changed files with 177 additions and 236 deletions

View File

@ -2,7 +2,7 @@
import Link from "next/link";
import { styled } from "@mui/system";
import { ISidebarLink } from "@/interfaces/SidebarLink.interfaces";
import { ISidebarLink } from "@/app/features/dashboard/sidebar/SidebarLink.interfaces";
const LinkContainer = styled("div")(({ theme }) => ({
display: "flex",

View File

@ -0,0 +1,20 @@
// app/dashboard/loading.tsx
"use client";
import CircularProgress from "@mui/material/CircularProgress";
import { styled } from "@mui/system";
const LoaderWrapper = styled("div")({
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center",
});
export default function Loading() {
return (
<LoaderWrapper>
<CircularProgress />
</LoaderWrapper>
);
}

View File

@ -1,11 +1,11 @@
// This ensures this component is rendered only on the client side
'use client';
"use client";
import TransactionTable from '@/app/components/Pages/Transactions/Transactions';
import TransactionTable from "@/app/features/Pages/transactions/Transactions";
export default function TransactionPage() {
return (
<div style={{ width: '100%' }}>
<div style={{ width: "100%" }}>
{/* This page will now be rendered on the client-side */}
<TransactionTable />
</div>

View File

@ -3,7 +3,6 @@ import MoreVertIcon from "@mui/icons-material/MoreVert";
import CalendarTodayIcon from "@mui/icons-material/CalendarToday";
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
import { DateRangePicker } from "../DateRangePicker/DateRangePicker";
// import { ArrowDropUp } from '@mui/icons-material';
const stats = [
{ label: "TOTAL", value: 5, change: "-84.85%" },
@ -63,8 +62,8 @@ export const GeneralHealthCard = () => {
</Box>
</Box>
<Box sx={{ display: "flex", justifyContent: "space-around", mt: 2 }}>
{stats.map((item) => (
<StatItem key={item.label} {...item} />
{stats.map((item, i) => (
<StatItem key={item.label + i} {...item} />
))}
</Box>
</CardContent>

View File

@ -1,43 +1,55 @@
'use client';
import { useState } from 'react';
"use client";
import { useState } from "react";
import {
Button, Dialog, DialogTitle, DialogContent, DialogActions,
FormControl, Select, MenuItem, FormControlLabel, Checkbox,
Stack, Paper, styled,
TextField
} from '@mui/material';
import FileUploadIcon from '@mui/icons-material/FileUpload';
import * as XLSX from 'xlsx';
import { saveAs } from 'file-saver';
import { DataGrid } from '@mui/x-data-grid';
import { columns } from './constants';
import { rows } from './mockData';
Button,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
FormControl,
Select,
MenuItem,
FormControlLabel,
Checkbox,
Stack,
Paper,
styled,
TextField,
} from "@mui/material";
import FileUploadIcon from "@mui/icons-material/FileUpload";
import * as XLSX from "xlsx";
import { saveAs } from "file-saver";
import { DataGrid } from "@mui/x-data-grid";
import { columns } from "./constants";
import { rows } from "./mockData";
const paginationModel = { page: 0, pageSize: 50 };
export default function TransactionTable() {
const [open, setOpen] = useState(false);
const [fileType, setFileType] = useState<'csv' | 'xls' | 'xlsx'>('csv');
const [fileType, setFileType] = useState<"csv" | "xls" | "xlsx">("csv");
const [onlyCurrentTable, setOnlyCurrentTable] = useState(false);
const handleExport = () => {
const exportRows = onlyCurrentTable ? rows.slice(0, 5) : rows;
const exportData = [
columns.map(col => col.headerName),
columns.map((col) => col.headerName),
// @ts-expect-error - Dynamic field access from DataGrid columns
...exportRows.map(row => columns.map(col => row[col.field] ?? '')),
...exportRows.map((row) => columns.map((col) => row[col.field] ?? "")),
];
const worksheet = XLSX.utils.aoa_to_sheet(exportData);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Transactions');
XLSX.utils.book_append_sheet(workbook, worksheet, "Transactions");
if (fileType === 'csv') {
if (fileType === "csv") {
const csv = XLSX.utils.sheet_to_csv(worksheet);
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
saveAs(blob, 'transactions.csv');
const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
saveAs(blob, "transactions.csv");
} else {
XLSX.writeFile(workbook, `transactions.${fileType}`, { bookType: fileType });
XLSX.writeFile(workbook, `transactions.${fileType}`, {
bookType: fileType,
});
}
setOpen(false);
@ -45,7 +57,12 @@ export default function TransactionTable() {
return (
<StyledPaper>
<Stack direction="row" justifyContent="space-between" alignItems="center" p={2}>
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
p={2}
>
<TextField
label="Search"
variant="outlined"
@ -67,7 +84,7 @@ export default function TransactionTable() {
rows={rows}
columns={columns}
initialState={{ pagination: { paginationModel } }}
pageSizeOptions={[50 , 100]}
pageSizeOptions={[50, 100]}
sx={{ border: 0 }}
/>
@ -78,7 +95,9 @@ export default function TransactionTable() {
<FormControl fullWidth sx={{ mt: 2 }}>
<Select
value={fileType}
onChange={(e) => setFileType(e.target.value as 'csv' | 'xls' | 'xlsx')}
onChange={(e) =>
setFileType(e.target.value as "csv" | "xls" | "xlsx")
}
>
<MenuItem value="csv">CSV</MenuItem>
<MenuItem value="xls">XLS</MenuItem>
@ -98,7 +117,9 @@ export default function TransactionTable() {
</DialogContent>
<DialogActions>
<Button onClick={() => setOpen(false)}>Cancel</Button>
<Button variant="contained" onClick={handleExport}>Export</Button>
<Button variant="contained" onClick={handleExport}>
Export
</Button>
</DialogActions>
</Dialog>
</StyledPaper>
@ -106,5 +127,5 @@ export default function TransactionTable() {
}
const StyledPaper = styled(Paper)(() => ({
height: '90vh',
height: "90vh",
}));

View File

@ -35,7 +35,7 @@ export const SectionCard = ({ title, icon, items }: ISectionCardProps) => (
<Divider />
<List dense disablePadding>
{items.map((item, index) => (
<ListItem key={index} disableGutters>
<ListItem key={item.title + index} disableGutters>
<ListItemText
primary={item.title}
secondary={item.date}

View File

@ -30,8 +30,8 @@ export const TransactionsOverviewTable = () => {
</TableRow>
</TableHead>
<TableBody>
{data1.map((row) => (
<TableRow key={row.state}>
{data1.map((row, i) => (
<TableRow key={row.state + i}>
<TableCell align="center">
<Box
sx={{

View File

@ -168,8 +168,8 @@ export const TransactionsWaitingApproval = () => {
</TableRow>
</TableHead>
<TableBody>
{transactions.map((tx) => (
<TableRow key={tx.id}>
{transactions.map((tx, i) => (
<TableRow key={tx.id + i}>
<TableCell>{tx.id}</TableCell>
<TableCell>{tx.user}</TableCell>
<TableCell>{tx.created}</TableCell>

View File

@ -5,4 +5,5 @@ export const Em = styled("em")(() => ({
alignItems: "center",
opacity: 0.7,
fontStyle: "normal",
color: "white",
}));

View File

@ -7,8 +7,8 @@ import {
SelectChangeEvent,
} from "@mui/material";
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import { SIDEBAR_LINKS } from "@/constants/SidebarLink.constants";
import { ISidebarLink } from "@/interfaces/SidebarLink.interfaces";
import { SIDEBAR_LINKS } from "@/app/features/dashboard/sidebar/SidebarLink.constants";
import { ISidebarLink } from "@/app/features/dashboard/sidebar/SidebarLink.interfaces";
import { Em } from "./DropDown.styled";
import PageLinks from "../../../../components/PageLinks/PageLinks";
@ -35,6 +35,7 @@ export default function SidebarDropdown({ onChange }: Props) {
MenuProps={{
PaperProps: {
style: {
backgroundColor: "rgba(30, 30, 30, 0.7)", // 0.9 opacity
maxHeight: 200,
},
},

View File

@ -1,8 +1,7 @@
import { styled } from '@mui/system';
import { styled } from "@mui/system";
export const LayoutWrapper = styled('div')({
display: 'flex',
width: '100%',
height: '100vh',
// overflow: 'hidden',
export const LayoutWrapper = styled("div")({
display: "flex",
width: "100%",
height: "100vh",
});

View File

@ -3,7 +3,7 @@
import React from "react";
import DashboardIcon from "@mui/icons-material/Dashboard";
import { styled } from "@mui/system";
import { SIDEBAR_LINKS } from "@/constants/SidebarLink.constants";
import { SIDEBAR_LINKS } from "@/app/features/dashboard/sidebar/SidebarLink.constants";
import PageLinks from "../../../components/PageLinks/PageLinks";
const SideBarContainer = styled("aside")(({ theme }) => ({

View File

@ -8,7 +8,7 @@ import GavelIcon from "@mui/icons-material/Gavel";
import HubIcon from "@mui/icons-material/Hub";
import AdminPanelSettingsIcon from "@mui/icons-material/AdminPanelSettings";
import InsightsIcon from "@mui/icons-material/Insights";
import { ISidebarLink } from "@/interfaces/SidebarLink.interfaces";
import { ISidebarLink } from "@/app/features/dashboard/sidebar/SidebarLink.interfaces";
export const SIDEBAR_LINKS: ISidebarLink[] = [
{ title: "Home", path: "/dashboard", icon: HomeIcon },

View File

@ -1,41 +0,0 @@
'use client';
import Link from 'next/link';
import { styled } from '@mui/system';
import { ISidebarLink } from '@/interfaces/SidebarLink.interfaces';
const LinkContainer = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
padding: '12px 1px',
borderRadius: '4px',
color: theme.palette.text.tertiary,
textDecoration: 'none',
transition: 'background 0.2s ease-in-out',
'&:hover': {
color: 'rgb(255, 255, 255)',
background: 'rgba(255, 255, 255, 0.08)',
backgroundColor: theme.palette.action.hover,
cursor: 'pointer',
},
}));
const LinkText = styled('span')(({ theme }) => ({
color: theme.palette.text.tertiary,
marginLeft: '12px',
fontWeight: 500,
}));
export default function SidebarLink({ title, path, icon: Icon }: ISidebarLink) {
return (
<Link href={path} passHref legacyBehavior>
<a style={{ textDecoration: 'none' }}>
<LinkContainer>
{Icon && <Icon />}
<LinkText>{title}</LinkText>
</LinkContainer>
</a>
</Link>
);
}

View File

@ -1,73 +0,0 @@
'use client';
import React from 'react';
import { styled } from '@mui/system';
import DashboardIcon from '@mui/icons-material/Dashboard';
import { SIDEBAR_LINKS } from '@/constants/SidebarLink.constants';
import SideBarLink from './SideBarLink';
// SideBar Container (styled using MUI System)
export const SideBar = styled('div')(({ theme }) => ({
width: '240px',
backgroundColor: theme.palette.background.primary,
color: 'white',
padding: theme.spacing(2),
height: '100vh',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
transition: 'width 0.3s ease', // Transition for resizing
}));
// Main Content Area
export const MainContent = styled('div')(({ theme }) => ({
flexGrow: 1,
padding: theme.spacing(4),
backgroundColor: theme.palette.background.default,
minHeight: '100vh',
overflowY: 'auto',
}));
// SideBar Header
export const SideBarHeader = styled('div')(({ theme }) => ({
marginBottom: theme.spacing(2),
fontSize: '20px',
fontWeight: 600,
display: 'flex',
alignItems: 'center',
}));
// Page Wrapper that holds SideBar and Content
export const LayoutWrapper = styled('div')({
display: 'flex',
flexDirection: 'row',
height: '100vh',
});
interface SideBarLayoutProps {
children: React.ReactNode; // Add children to accept passed content
}
const SideBarLayout: React.FC<SideBarLayoutProps> = ({ children }) => {
return (
<LayoutWrapper>
<SideBar>
<SideBarHeader>
PaymentIQ
<DashboardIcon sx={{ marginLeft: 0.5 }} />
</SideBarHeader>
{SIDEBAR_LINKS.map((link) => (
<SideBarLink
key={link.path}
title={link.title}
path={link.path}
icon={link.icon}
/>
))}
</SideBar>
<MainContent>{children}</MainContent> {/* Render children here */}
</LayoutWrapper>
);
};
export default SideBarLayout;

View File

@ -0,0 +1,11 @@
// utils/defineStyles.ts
import type { SxProps, Theme } from "@mui/material/styles";
/**
* Helper to define style objects with full key/type inference as SxProps<Theme>
*/
export function defineStyles<T extends Record<string, SxProps<Theme>>>(
styles: T
): T {
return styles;
}

View File

@ -1,10 +1,13 @@
"use client";
'use client';
import { ThemeProvider, CssBaseline } from "@mui/material";
import theme from "./theme";
import { ThemeProvider, CssBaseline } from '@mui/material';
import theme from './theme';
export default function ThemeRegistry({ children }: { children: React.ReactNode }) {
export default function ThemeRegistry({
children,
}: {
children: React.ReactNode;
}) {
return (
<ThemeProvider theme={theme}>
<CssBaseline />