feat: major mods

- added graph on dashboard
- added recent txns

Signed-off-by: Ameya Shenoy <shenoy.ameya@gmail.com>
This commit is contained in:
Ameya Shenoy 2023-03-10 19:37:00 +05:30
parent 89d64c609d
commit 6a9ab237a5
Signed by: codingcoffee
GPG key ID: EEC8EA855D61CEEC
24 changed files with 2135 additions and 5 deletions

View file

@ -0,0 +1,31 @@
import React from 'react'
import styles from './bank.module.css'
import { FiCheck } from 'react-icons/fi';
import Image from 'next/image'
export default function Bank(props) {
return (
<div className={styles.bankBalance}>
<div className={styles.left}>
<div className={styles.checkHolder}>
<FiCheck
className={styles.check}
size={15}
/>
</div>
<Image
src={props.bankLogoSrc}
alt={`${props.bankName} Logo`}
className={styles.bankLogo}
width={28}
height={28}
priority
/>
</div>
<div className={styles.accountBalance}>
{props.bankBalance}
</div>
</div>
)
}

View file

@ -0,0 +1,89 @@
"use client"
import React from 'react'
import dayjs, { Dayjs } from 'dayjs';
import styles from './calendar.module.css'
import { CalendarPicker } from '@mui/x-date-pickers/CalendarPicker';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { styled } from '@mui/material/styles';
import { PickersDay, PickersDayProps } from '@mui/x-date-pickers/PickersDay';
interface CustomPickerDayProps extends PickersDayProps<Dayjs> {
dayIsBetween: boolean;
isFirstDay: boolean;
isLastDay: boolean;
}
const CustomPickersDay = styled(PickersDay, {
shouldForwardProp: (prop) =>
prop !== 'dayIsBetween' && prop !== 'isFirstDay' && prop !== 'isLastDay',
})<CustomPickerDayProps>(({ theme, dayIsBetween, isFirstDay, isLastDay }) => ({
...(dayIsBetween && {
borderRadius: 0,
backgroundColor: theme.palette.primary.main,
color: theme.palette.common.white,
'&:hover, &:focus': {
backgroundColor: theme.palette.primary.dark,
},
}),
...(isFirstDay && {
borderTopLeftRadius: '50%',
borderBottomLeftRadius: '50%',
}),
...(isLastDay && {
borderTopRightRadius: '50%',
borderBottomRightRadius: '50%',
}),
})) as React.ComponentType<CustomPickerDayProps>;
export default function RecurringCol() {
const [value, setValue] = React.useState<Dayjs | null>(dayjs('2021-01-23'));
const theme = createTheme({
components: {
// Name of the component
MuiButtonBase: {
defaultProps: {
// The props to change the default for.
disableRipple: true, // No more ripple, on the whole application 💣!
},
},
},
});
const renderWeekPickerDay = (
date: Dayjs,
selectedDates: Array<Dayjs | null>,
pickersDayProps: PickersDayProps<Dayjs>,
) => {
if (!value) {
return <PickersDay {...pickersDayProps} />;
}
return (
<CustomPickersDay
{...pickersDayProps}
/>
);
};
return (
<div className={styles.calendarDiv}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<ThemeProvider theme={theme}>
<CalendarPicker
date={value}
onChange={(newDate) => setValue(newDate)}
showDaysOutsideCurrentMonth={true}
renderDay={renderWeekPickerDay}
/>
</ThemeProvider>
</LocalizationProvider>
</div>
)
}

View file

@ -0,0 +1,17 @@
import styles from './centerCol.module.css'
import React from 'react'
import Dashboard from './Dashboard'
export default function CenterCol() {
return (
<div className={styles.main}>
<div className={styles.title}>
<div className={styles.greeting}>Good morning, Nishant</div>
<div className={styles.date}>It's 3rd of January, a Monday</div>
</div>
<Dashboard />
</div>
)
}

View file

@ -0,0 +1,68 @@
import React from 'react'
import styles from './dashboard.module.css'
import Bank from './Bank'
import Graph from './Graph'
import { AiOutlineBank } from 'react-icons/ai';
import { BiRupee } from 'react-icons/bi';
export default function Dashboard() {
return (
<div className={styles.main}>
<div className={styles.banks}>
<div
className={styles.title}
>
<AiOutlineBank
className={styles.banksLogo}
size={25}
/>
Banks
</div>
<Bank
bankLogoSrc="/sbi.svg"
bankName="SBI"
bankBalance="27,932"
/>
<Bank
bankLogoSrc="/icici.svg"
bankName="ICICI"
bankBalance="7,932"
/>
<Bank
bankLogoSrc="/hdfc.svg"
bankName="HDFC"
bankBalance="2,58,630"
/>
<Bank
bankLogoSrc="/axis.svg"
bankName="Axis"
bankBalance="55,410"
/>
</div>
<div className={styles.totalBalance}>
<div
className={styles.title}
>
<div className={styles.rupeeHolder}>
<BiRupee
className={styles.rupeeLogo}
size={20}
/>
</div>
Total Balance
</div>
<div className={styles.totalBalanceAmountHolder}>
<div></div>
<div className={styles.amount}>3,49,904</div>
</div>
<div className={styles.message}>
20% compared to previous month
</div>
<Graph />
</div>
</div>
)
}

View file

@ -0,0 +1,78 @@
"use client"
import React from 'react'
import Chart from 'chart.js/auto';
import styles from './graph.module.css'
export default function Graph() {
return (
<canvas
id="chart"
width="400"
height="200"
ref={
node => {
if (node) {
var ctx = node.getContext("2d");
/*** Gradient ***/
var gradient = ctx.createLinearGradient(0, 0, 0, 300);
gradient.addColorStop(0, 'rgba(82, 183, 97, 1)');
gradient.addColorStop(1, 'rgba(82, 183, 97, 0)');
/***************/
var data = {
labels : ["NOV 15", "NOV 30", "DEC 15", "DEC 31", "JAN 15"],
datasets: [
{
label: "",
fill: true,
backgroundColor: gradient,
data : [25.0, 25.0, 30.0, 27.0, 27.0, 19.0]
}
]
};
var options = {
responsive: true,
plugins: {
legend: {
display: false,
}
},
scales: {
x: {
border: {
display: false,
},
grid: {
display: false,
},
},
y: {
border: {
display: false,
},
grid: {
display: false,
},
ticks: {
display: false,
}
}
}
};
new Chart(ctx, {
type: "line",
data: data,
options: options,
});
}
}
}
>
</canvas>
)
}

View file

@ -0,0 +1,46 @@
import React from 'react'
import styles from './recentTnx.module.css'
import { BsTriangleFill } from 'react-icons/bs';
import SingleTransaction from './SingleTransaction'
export default function RecentTransactions() {
return (
<div className={styles.main}>
<div className={styles.heading}>
<div className={styles.hRecTnx}>Recent Transactions</div>
<div className={styles.hSeeAll}>See All</div>
</div>
<div className={styles.options}>
<div className={styles.optionButton}>
<div>All transactions</div>
<div>
<BsTriangleFill
size={10}
className={styles.arrow}
color="#676483"
/>
</div>
</div>
<div className={styles.optionButton}>
<div>All banks</div>
<div>
<BsTriangleFill
size={10}
className={styles.arrow}
color="#676483"
/>
</div>
</div>
</div>
<div>
<SingleTransaction />
<SingleTransaction />
<SingleTransaction />
<SingleTransaction />
</div>
</div>
)
}

View file

@ -0,0 +1,28 @@
import styles from './recurringCol.module.css'
import Calendar from './Calendar'
import { AiOutlinePlus } from 'react-icons/ai';
import { VscDebugRestart } from 'react-icons/vsc';
import React from 'react'
export default function RecurringCol() {
return (
<div className={styles.main}>
<div className={styles.topDiv}>
<div className={styles.titleDiv}>
<div className={styles.titleLeft}>
<div className={styles.restart}>
<VscDebugRestart />
</div>
<div className={styles.titleText}>Recurring Payments</div>
</div>
<AiOutlinePlus
size={20}
className={styles.plus}
/>
</div>
<Calendar />
</div>
</div>
)
}

View file

@ -0,0 +1,22 @@
import React from 'react'
import styles from './singleTnx.module.css'
export default function SingleTransaction() {
return (
<div className={styles.tnx}>
<div className={styles.tnxHeading}>
<div className={styles.tnxTitle}>Fenny's Banglore</div>
<div className={styles.date}>Today, 11:17 AM</div>
</div>
<div className={styles.tnxInfo}>
<div className={styles.cost}>
<div className={styles.minus}>-</div>
<div className={styles.rupee}></div>
<div className={styles.amount}>3,940</div>
</div>
<div className={styles.tag}>Tag</div>
</div>
</div>
)
}

View file

@ -0,0 +1,47 @@
.bankBalance {
margin-left: 30px;
margin-bottom: 10px;
border-radius: 10px;
background: #F0F1F5;
color: #7A799B;
width: 200px;
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
}
.left {
display: flex;
align-items: center;
}
.check {
background: #CBCADD;
color: #212439;
border-radius: 50%;
}
.checkHolder {
margin-left: 15px;
display: flex;
align-items: center;
justify-content: center;
background: #CBCADD;
border-radius: 50%;
aspect-ratio: 1;
width: 20px;
}
.accountBalance {
color: #7D7BA0;
margin-right: 15px;
font-weight: bold;
}
.bankLogo {
margin-left: 15px;
}

View file

@ -0,0 +1,4 @@
.calendarDiv {
color: #676D91;
}

View file

@ -0,0 +1,21 @@
.main {
flex-grow: 1;
}
.title {
text-transform: uppercase;
padding-left: 40px;
}
.greeting {
padding-top: 10px;
color: #7F7C9A;
font: bold 1.2em Arial, Sans-serif;
}
.date {
color: #2F2D45;
font: bold 1.35em Arial, Sans-serif;
padding-top: 20px;
}

View file

@ -0,0 +1,58 @@
.main {
background: #FFFFFF;
border-radius: 20px;
display: flex;
margin-top: 40px;
}
.title {
display: flex;
align-items: center;
color: #6D678E;
margin: 35px 25px;
font: bold 1em Arial, Sans-serif;
text-transform: uppercase;
}
.banks {
flex: 1;
}
.banksLogo {
margin: 0 10px;
}
.rupeeHolder {
margin: 0 10px;
display: flex;
align-items: center;
justify-content: center;
aspect-ratio: 1;
background: #6C6F7E;
border-radius: 50%;
width: 23px;
}
.rupeeLogo {
background: #6C6F7E;
border-radius: 50%;
color: #FFFFFF;
}
.totalBalance {
flex: 2;
}
.totalBalanceAmountHolder {
display: flex;
margin: 35px 25px;
}
.amount {
font: bold 4em Arial, Sans-serif;
}
.message {
margin: 35px 25px;
}

View file

@ -0,0 +1,4 @@
.main {
border: 2px solid red;
}

View file

@ -0,0 +1,54 @@
.main {
width: 400px;
}
.heading {
display: flex;
flex-direction: row;
justify-content: space-between;
text-transform: uppercase;
padding: 20px 0;
}
.hRecTnx {
font: bold 1.1em Arial, Sans-serif;
color: #787495;
}
.hSeeAll {
font: bold 1.1em Sans-serif;
color: #302D46;
}
.optionButton {
border: 1px solid #D7D8DD;
border-radius: 10px;
display: flex;
flex-direction: row;
flex-grow: 1;
flex-basis: 0;
justify-content: space-between;
align-items: center;
font: 1.1em Arial, Sans-serif;
height: 50px;
padding: 20px;
color: #413A6E;
}
.options {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-bottom: 30px;
gap: 10px;
}
.arrow {
transform: scaleY(-1);
-moz-transform: scaleY(-1);
-webkit-transform: scaleY(-1);
-ms-transform: scaleY(-1);
}

View file

@ -0,0 +1,45 @@
.main {
background: #20284C;
width: 400px;
border-radius: 20px 20px 0 0;
padding: 30px 20px;
}
.topDiv {
}
.titleDiv {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
color: #EBF4F1;
text-transform: uppercase;
font-weight: bold;
}
.titleText {
padding-left: 10px;
font: bold 1.1em Arial, Sans-serif;
}
.plus {
margin-right: 20px;
}
.restart {
display: flex;
justify-content: center;
align-items: center;
background: #FBFFF8;
color: #20284C;
border-radius: 50%;
aspect-ratio: 1;
width: 25px;
}
.titleLeft {
display: flex;
align-items: center;
}

View file

@ -0,0 +1,72 @@
.tnx {
background: #FFFFFF;
border-radius: 20px;
margin-bottom: 10px;
box-shadow: 5px 5px 5px #DBD9E4;
}
.tnxHeading {
display: flex;
flex-direction: row;
justify-content: space-between;
border-bottom: 3px solid #F0EFF5;
height: 50px;
align-items: center;
padding: 20px;
color: #9390A9;
}
.date {
color: #9390A9;
font: 1.2em Sans-serif;
font-weight: 500;
}
.tag {
border: 2px solid #DDDCE4;
border-radius: 10px;
background: #F1F0F5;
color: #263D5F;
padding: 10px 12px;
font: 1.2em Sans-serif;
font-weight: 600;
}
.tnxTitle {
text-overflow: ellipsis;
font: 1.3em Sans-serif;
font-weight: 500;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 110px;
overflow: hidden;
}
.tnxInfo {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100px;
align-items: center;
padding: 20px;
}
.cost {
display: flex;
}
.minus {
color: #C4C2CC;
font: bold 2em Sans-serif;
}
.rupee {
color: #28274F;
font: 1.2em Sans-serif;
}
.amount {
color: #28274F;
font: bold 2em Sans-serif;
}

View file

@ -1,10 +1,11 @@
.main {
display: flex;
flex-direction: column;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 6rem;
min-height: 100vh;
width: 100vw;
gap: 30px;
}

View file

@ -1,12 +1,15 @@
import styles from './page.module.css'
import RecurringCol from './components/RecurringCol'
import CenterCol from './components/CenterCol'
import RecentTransactions from './components/RecentTransactions'
export default function Home() {
return (
<main className={styles.main}>
<div>
Hi, Hello
</div>
<RecurringCol />
<CenterCol />
<RecentTransactions />
</main>
)
}

1382
web/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -9,9 +9,15 @@
"lint": "next lint"
},
"dependencies": {
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@mui/material": "^5.11.11",
"@mui/x-date-pickers": "^5.0.20",
"@types/node": "18.14.1",
"@types/react": "18.0.28",
"@types/react-dom": "18.0.11",
"chart.js": "^4.2.1",
"dayjs": "^1.11.7",
"eslint": "8.35.0",
"eslint-config-next": "13.2.1",
"next": "^13.2.3",

20
web/public/axis.svg Normal file
View file

@ -0,0 +1,20 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1552 1346" width="1552" height="1346">
<title>AXISBank_Logo-svg (2)-svg</title>
<style>
.s0 { fill: #97144d }
</style>
<g id="layer1">
<g id="g870">
<g id="Clip-Path: g872">
<g id="g872">
<g id="g878">
<path id="path880" class="s0" d="m1551.8 1345.7h-482.5l-293-511.2h482.5z"/>
</g>
<g id="g882">
<path id="path884" class="s0" d="m774.5 0.2l242 416.4-534.5 929.1h-481.7z"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 530 B

18
web/public/hdfc.svg Normal file
View file

@ -0,0 +1,18 @@
<svg version="1.2" baseProfile="tiny-ps" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1679 1678" width="1679" height="1678">
<title>HDFC_Bank_Logo-svg</title>
<style>
tspan { white-space:pre }
.shp0 { fill: #ed232a }
.shp1 { fill: #ffffff }
.shp2 { fill: #004c8f }
</style>
<g id="layer1">
<g id="g11008">
<path id="path1576" class="shp0" d="M0.51 0.83L1678.51 0.83L1678.51 1677.6L0.51 1677.6L0.51 0.83Z" />
<path id="path1578" class="shp1" d="M294.21 294.31L1385.02 294.31L1385.02 1384.33L294.21 1384.33L294.21 294.31Z" />
<path id="path1580" class="shp1" d="M755.64 0.83L923.38 0.83L923.38 1677.6L755.64 1677.6L755.64 0.83Z" />
<path id="path1582" class="shp1" d="M0.51 755.62L1678.51 755.62L1678.51 923.23L0.51 923.23L0.51 755.62Z" />
<path id="path1584" class="shp2" d="M587.91 587.79L1091.33 587.79L1091.33 1090.84L587.91 1090.84L587.91 587.79Z" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 908 B

15
web/public/icici.svg Normal file
View file

@ -0,0 +1,15 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1388 1505" width="1388" height="1505">
<title>ICICI_Bank_Logo-svg</title>
<style>
.s0 { fill: #f06321 }
.s1 { fill: #ae282e }
.s2 { fill: #ffffff }
</style>
<g id="layer1">
<g id="g651">
<path id="path160" class="s0" d="m393.4 327.4c343-340.8 759.2-429.2 925.7-197 166.6 232.3 20.2 701.7-322.8 1042.4-343.1 343.2-759.2 431.5-928.3 196.8-163.9-234.7-17.5-701.7 325.4-1042.2z"/>
<path id="path162" class="s1" d="m1319.1 130.4c58 85.8 75.7 199.5 63.1 328.1-45.4 174.1-156.4 361-322.9 522.4-307.7 300.4-676 376.1-829.8 171.7-148.9-204.5-22.7-613.3 277.5-911 37.8-35.5 75.6-68.3 113.5-96 285-181.8 567.5-196.8 698.6-15.2z"/>
<path id="path164" class="s2" d="m1054.3 183.4v7.6c-2.6 42.9-27.8 95.9-73.2 141.3-68 65.6-158.8 90.8-196.8 53.1-42.8-40.4-17.5-128.8 50.6-199.5 70.6-68.1 161.4-90.8 199.2-50.4 12.6 12.6 20.2 27.7 20.2 47.9zm-262.3 1158.4c-161.5 121.1-327.9 181.8-489.4 156.6 68.1 2.5 123.7-73.3 169.1-174.2 45.4-103.5 70.6-199.3 93.3-290.3 32.8-143.8 35.3-244.7 17.6-267.4-27.7-35.5-88.2-27.8-158.9 12.6-35.3 20.2-80.7 7.6-27.6-58 55.4-65.6 269.7-222.2 345.4-247.4 85.8-22.7 181.6 10.1 148.9 103.4-22.9 68.1-320.4 845.5-98.4 764.7z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

1
web/public/sbi.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="2499" height="2500" viewBox="0 -0.06 499.999 500.119"><path d="M499.999 250c.033 138.071-111.869 250.026-249.94 250.06C111.989 500.092.032 388.189 0 250.118V250C-.033 111.929 111.869-.026 249.941-.06 388.012-.092 499.967 111.81 500 249.881l-.001.119z" fill="#156dd1"/><path d="M295 250c0 24.853-20.147 45-45 45-24.854 0-45-20.147-45-45s20.146-45 45-45c24.853 0 45 20.147 45 45z" fill="#fff"/><path fill="#fff" d="M234.483 282.756h31.035V500h-31.035z"/></svg>

After

Width:  |  Height:  |  Size: 505 B