Touch Up Dashboard

This commit is contained in:
2022-05-26 15:14:34 +07:00
parent 79c4a5c241
commit e8bb61be2f
19 changed files with 993 additions and 502 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

After

Width:  |  Height:  |  Size: 573 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@@ -17,36 +17,7 @@ export default function Logo({ disabledLink = false, sx }: Props) {
const logo = (
<Box sx={{ width: 40, height: 40, ...sx }}>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 512 512">
<defs>
<linearGradient id="BG1" x1="100%" x2="50%" y1="9.946%" y2="50%">
<stop offset="0%" stopColor={PRIMARY_DARK} />
<stop offset="100%" stopColor={PRIMARY_MAIN} />
</linearGradient>
<linearGradient id="BG2" x1="50%" x2="50%" y1="0%" y2="100%">
<stop offset="0%" stopColor={PRIMARY_LIGHT} />
<stop offset="100%" stopColor={PRIMARY_MAIN} />
</linearGradient>
<linearGradient id="BG3" x1="50%" x2="50%" y1="0%" y2="100%">
<stop offset="0%" stopColor={PRIMARY_LIGHT} />
<stop offset="100%" stopColor={PRIMARY_MAIN} />
</linearGradient>
</defs>
<g fill={PRIMARY_MAIN} fillRule="evenodd" stroke="none" strokeWidth="1">
<path
fill="url(#BG1)"
d="M183.168 285.573l-2.918 5.298-2.973 5.363-2.846 5.095-2.274 4.043-2.186 3.857-2.506 4.383-1.6 2.774-2.294 3.939-1.099 1.869-1.416 2.388-1.025 1.713-1.317 2.18-.95 1.558-1.514 2.447-.866 1.38-.833 1.312-.802 1.246-.77 1.18-.739 1.111-.935 1.38-.664.956-.425.6-.41.572-.59.8-.376.497-.537.69-.171.214c-10.76 13.37-22.496 23.493-36.93 29.334-30.346 14.262-68.07 14.929-97.202-2.704l72.347-124.682 2.8-1.72c49.257-29.326 73.08 1.117 94.02 40.927z"
/>
<path
fill="url(#BG2)"
d="M444.31 229.726c-46.27-80.956-94.1-157.228-149.043-45.344-7.516 14.384-12.995 42.337-25.267 42.337v-.142c-12.272 0-17.75-27.953-25.265-42.337C189.79 72.356 141.96 148.628 95.69 229.584c-3.483 6.106-6.828 11.932-9.69 16.996 106.038-67.127 97.11 135.667 184 137.278V384c86.891-1.611 77.962-204.405 184-137.28-2.86-5.062-6.206-10.888-9.69-16.994"
/>
<path
fill="url(#BG3)"
d="M450 384c26.509 0 48-21.491 48-48s-21.491-48-48-48-48 21.491-48 48 21.491 48 48 48"
/>
</g>
</svg>
<img src="/logo/logo-linksehat.png" alt="LinkSehat" />
</Box>
);

View File

@@ -14,7 +14,7 @@ interface Props extends BoxProps {
const Page = forwardRef<HTMLDivElement, Props>(({ children, title = '', meta, ...other }, ref) => (
<>
<Helmet>
<title>{`${title} | Minimal-UI`}</title>
<title>{`${title} | LinkSehat`}</title>
{meta}
</Helmet>

View File

@@ -0,0 +1,191 @@
import { ApexOptions } from 'apexcharts';
// @mui
import { useTheme } from '@mui/material/styles';
// ----------------------------------------------------------------------
export default function BaseOptionChart(): ApexOptions {
const theme = useTheme();
const LABEL_TOTAL = {
show: true,
label: 'Total',
color: theme.palette.text.secondary,
fontSize: theme.typography.subtitle2.fontSize as string,
fontWeight: theme.typography.subtitle2.fontWeight,
lineHeight: theme.typography.subtitle2.lineHeight,
};
const LABEL_VALUE = {
offsetY: 8,
color: theme.palette.text.primary,
fontSize: theme.typography.h3.fontSize as string,
fontWeight: theme.typography.h3.fontWeight,
lineHeight: theme.typography.h3.lineHeight,
};
return {
// Colors
colors: [
theme.palette.primary.main,
theme.palette.chart.yellow[0],
theme.palette.chart.blue[0],
theme.palette.chart.violet[0],
theme.palette.chart.green[0],
theme.palette.chart.red[0],
],
// Chart
chart: {
toolbar: { show: false },
zoom: { enabled: false },
// animations: { enabled: false },
foreColor: theme.palette.text.disabled,
fontFamily: theme.typography.fontFamily,
},
// States
states: {
hover: {
filter: {
type: 'lighten',
value: 0.04,
},
},
active: {
filter: {
type: 'darken',
value: 0.88,
},
},
},
// Fill
fill: {
opacity: 1,
gradient: {
type: 'vertical',
shadeIntensity: 0,
opacityFrom: 0.4,
opacityTo: 0,
stops: [0, 100],
},
},
// Datalabels
dataLabels: { enabled: false },
// Stroke
stroke: {
width: 3,
curve: 'smooth',
lineCap: 'round',
},
// Grid
grid: {
strokeDashArray: 3,
borderColor: theme.palette.divider,
},
// Xaxis
xaxis: {
axisBorder: { show: false },
axisTicks: { show: false },
},
// Markers
markers: {
size: 0,
strokeColors: theme.palette.background.paper,
},
// Tooltip
tooltip: {
x: {
show: false,
},
},
// Legend
legend: {
show: true,
fontSize: String(13),
position: 'top',
horizontalAlign: 'right',
markers: {
radius: 12,
},
fontWeight: 500,
itemMargin: { horizontal: 12 },
labels: {
colors: theme.palette.text.primary,
},
},
// plotOptions
plotOptions: {
// Bar
bar: {
columnWidth: '28%',
borderRadius: 4,
},
// Pie + Donut
pie: {
donut: {
labels: {
show: true,
value: LABEL_VALUE,
total: LABEL_TOTAL,
},
},
},
// Radialbar
radialBar: {
track: {
strokeWidth: '100%',
background: theme.palette.grey[500_16],
},
dataLabels: {
value: LABEL_VALUE,
total: LABEL_TOTAL,
},
},
// Radar
radar: {
polygons: {
fill: { colors: ['transparent'] },
strokeColors: theme.palette.divider,
connectorColors: theme.palette.divider,
},
},
// polarArea
polarArea: {
rings: {
strokeColor: theme.palette.divider,
},
spokes: {
connectorColors: theme.palette.divider,
},
},
},
// Responsive
responsive: [
{
// sm
breakpoint: theme.breakpoints.values.sm,
options: {
plotOptions: { bar: { columnWidth: '40%' } },
},
},
{
// md
breakpoint: theme.breakpoints.values.md,
options: {
plotOptions: { bar: { columnWidth: '32%' } },
},
},
],
};
}

View File

@@ -0,0 +1,58 @@
// @mui
import { alpha, useTheme } from '@mui/material/styles';
import { GlobalStyles } from '@mui/material';
// utils
import cssStyles from '../../utils/cssStyles';
// ----------------------------------------------------------------------
export default function ChartStyle() {
const theme = useTheme();
return (
<GlobalStyles
styles={{
'&.apexcharts-canvas': {
// Tooltip
'.apexcharts-xaxistooltip': {
...cssStyles(theme).bgBlur(),
border: 0,
color: theme.palette.text.primary,
boxShadow: theme.customShadows.dropdown,
borderRadius: Number(theme.shape.borderRadius) * 1.5,
'&:before': { borderBottomColor: 'transparent' },
'&:after': { borderBottomColor: alpha(theme.palette.background.default, 0.8) },
},
'.apexcharts-tooltip.apexcharts-theme-light': {
...cssStyles(theme).bgBlur(),
border: 0,
boxShadow: theme.customShadows.dropdown,
borderRadius: Number(theme.shape.borderRadius) * 1.5,
'& .apexcharts-tooltip-title': {
border: 0,
textAlign: 'center',
fontWeight: theme.typography.fontWeightBold,
backgroundColor: theme.palette.grey[500_16],
color: theme.palette.text[theme.palette.mode === 'light' ? 'secondary' : 'primary'],
},
},
// Legend
'.apexcharts-legend': {
padding: 0,
},
'.apexcharts-legend-series': {
display: 'flex !important',
alignItems: 'center',
},
'.apexcharts-legend-marker': {
marginRight: 8,
},
'.apexcharts-legend-text': {
lineHeight: '18px',
textTransform: 'capitalize',
},
},
}}
/>
);
}

View File

@@ -0,0 +1,2 @@
export { default as ChartStyle } from './ChartStyle';
export { default as BaseOptionChart } from './BaseOptionChart';

View File

@@ -2,7 +2,7 @@ import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
// @mui
import { styled, useTheme } from '@mui/material/styles';
import { Box, Stack, Drawer } from '@mui/material';
import { Box, Stack, Drawer, Typography } from '@mui/material';
// hooks
import useResponsive from '../../../hooks/useResponsive';
import useCollapseDrawer from '../../../hooks/useCollapseDrawer';
@@ -72,13 +72,19 @@ export default function NavbarVertical({ isOpenSidebar, onCloseSidebar }: Props)
...(isCollapse && { alignItems: 'center' }),
}}
>
<Stack direction="row" alignItems="center" justifyContent="space-between">
<Logo />
{isDesktop && !isCollapse && (
{isDesktop && !isCollapse ? (
<Stack direction="row" alignItems="center" justifyContent="space-between">
<Stack direction="row" alignItems="center">
<Logo />
<Typography ml={3}>PRIME CENTER</Typography>
</Stack>
<CollapseButton onToggleCollapse={onToggleCollapse} collapseClick={collapseClick} />
)}
</Stack>
</Stack>)
: (
<Stack direction="row" alignItems="center" justifyContent="space-between">
<Logo />
</Stack>
)}
<NavbarAccount isCollapse={isCollapse} />
</Stack>

View File

@@ -1,11 +1,13 @@
// @mui
import { Button, Container, Typography } from '@mui/material';
import { Button, Container, Grid, styled, Typography, Card, Stack } from '@mui/material';
// hooks
import useSettings from '../hooks/useSettings';
// components
import Page from '../components/Page';
import axios from '../utils/axios';
import useAuth from '../hooks/useAuth';
import SomethingUsage from '../sections/dashboard/SomethingUsage';
import { fCurrency } from '../utils/formatNumber';
// ----------------------------------------------------------------------
@@ -18,30 +20,47 @@ export default function Dashboard() {
axios.get('/user')
};
const DangerCard = styled(Card)(({ theme }) => ({
boxShadow: 'none',
padding: theme.spacing(3),
color: theme.palette.error.main,
backgroundColor: theme.palette.error.lighter,
}));
const SuccessCard = styled(Card)(({ theme }) => ({
boxShadow: 'none',
padding: theme.spacing(3),
color: theme.palette.success.darker,
backgroundColor: theme.palette.success.lighter,
}));
return (
<Page title="Dashboard">
<Container maxWidth={themeStretch ? false : 'xl'}>
<Typography variant="h3" component="h1" paragraph>
Dashboard
</Typography>
<Typography gutterBottom>
Curabitur turpis. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc,
vitae euismod ligula urna in dolor. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit
id, lorem. Phasellus blandit leo ut odio. Vestibulum ante ipsum primis in faucibus orci
luctus et ultrices posuere cubilia Curae; Fusce id purus. Aliquam lorem ante, dapibus in,
viverra quis, feugiat a, tellus. In consectetuer turpis ut velit. Aenean posuere, tortor
sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus.
Vestibulum suscipit nulla quis orci. Nam commodo suscipit quam. Sed a libero.
</Typography>
<Typography>
Praesent ac sem eget est egestas volutpat. Phasellus viverra nulla ut metus varius
laoreet. Curabitur ullamcorper ultricies nisi. Ut non enim eleifend felis pretium feugiat.
Donec mi odio, faucibus at, scelerisque quis, convallis in, nisi. Fusce vel dui. Quisque
libero metus, condimentum nec, tempor a, commodo mollis, magna. In enim justo, rhoncus ut,
imperdiet a, venenatis vitae, justo. Cras dapibus.
</Typography>
<Button onClick={loadSomething}>Something</Button>
<Button onClick={logout}>Logout</Button>
<Grid container spacing={2}>
<Grid item xs={6}>
<SomethingUsage />
</Grid>
<Grid item xs={6}>
<DangerCard>
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ mb: 0.6 }}>
<Typography sx={{ typography: 'subtitle2' }}>This Month Usages </Typography>
<Typography>{fCurrency(15000000)} (57)</Typography>
</Stack>
</DangerCard>
<br />
<SuccessCard>
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ mb: 0.6 }}>
<Typography sx={{ typography: 'subtitle2' }}>Remaining Balance Estimation </Typography>
<Typography>November 2022</Typography>
</Stack>
</SuccessCard>
</Grid>
</Grid>
</Container>
</Page>
);

View File

@@ -71,12 +71,15 @@ export default function Login() {
<Page title="Login">
<RootStyle>
<HeaderStyle>
<Logo />
<Logo sx={{ width: 150, height: 150 }} />
{smUp && (
<Typography variant="body2" sx={{ mt: { md: -2 } }}>
Dont have an account? {''}
<Link variant="subtitle2" component={RouterLink} to={PATH_AUTH.register}>
Get started
Has problem with your account? {''}
<Link variant="subtitle2" component={RouterLink} to="#" onClick={(e) => {
window.location.href = "mailto:admin@linksehat.com";
e.preventDefault();
}}>
Contact Us
</Link>
</Typography>
)}
@@ -101,7 +104,7 @@ export default function Login() {
<Stack direction="row" alignItems="center" sx={{ mb: 5 }}>
<Box sx={{ flexGrow: 1 }}>
<Typography variant="h4" gutterBottom>
Sign in to Minimal
Sign in to LinkSehat
</Typography>
<Typography sx={{ color: 'text.secondary' }}>Enter your details below.</Typography>
</Box>
@@ -119,7 +122,7 @@ export default function Login() {
<LoginForm />
{!smUp && (
{false && !smUp && (
<Typography variant="body2" align="center" sx={{ mt: 3 }}>
Dont have an account?{' '}
<Link variant="subtitle2" component={RouterLink} to={PATH_AUTH.register}>

View File

@@ -0,0 +1,80 @@
import merge from 'lodash/merge';
import ReactApexChart from 'react-apexcharts';
// @mui
import { styled } from '@mui/material/styles';
import { Card, Typography, Stack } from '@mui/material';
// utils
import { fCurrency, fPercent } from '../../utils/formatNumber';
// components
import Iconify from '../../components/Iconify';
import BaseOptionChart from '../../components/chart/BaseOptionChart';
// ----------------------------------------------------------------------
const RootStyle = styled(Card)(({ theme }) => ({
boxShadow: 'none',
padding: theme.spacing(3),
color: theme.palette.primary.darker,
backgroundColor: theme.palette.primary.lighter,
}));
// ----------------------------------------------------------------------
const INITIAL = 500000000
const TOTAL = 257907000;
const PERCENT = -3;
const CHART_DATA = [{ data: [100, 99, 99, 85, 74, 57, 54, 51] }];
export default function SomethingUsage() {
const chartOptions = merge(BaseOptionChart(), {
chart: { sparkline: { enabled: true } },
xaxis: { labels: { show: true } },
yaxis: { labels: { show: false } },
stroke: { width: 4 },
legend: { show: false },
grid: { show: false },
tooltip: {
marker: { show: false },
y: {
formatter: (seriesName: string) => (seriesName) + "%",
title: {
formatter: () => '',
},
},
},
fill: { gradient: { opacityFrom: 0, opacityTo: 0 } },
});
return (
<RootStyle>
<Stack direction="row" justifyContent="space-between" sx={{ mb: 3 }}>
<div>
<Typography variant="body2" component="span" sx={{ opacity: 0.72 }}>
{fCurrency(INITIAL)}
</Typography>
<Typography sx={{ typography: 'subtitle2' }}>Remaining Balance</Typography>
<Typography sx={{ typography: 'h3' }}>{fCurrency(TOTAL)}</Typography>
</div>
<div>
<Stack direction="row" alignItems="center" justifyContent="flex-end" sx={{ mb: 0.6 }}>
<Iconify
width={20}
height={20}
icon={PERCENT >= 0 ? 'eva:trending-up-fill' : 'eva:trending-down-fill'}
/>
<Typography variant="subtitle2" component="span" sx={{ ml: 0.5 }}>
{PERCENT > 0 && '+'}
{fPercent(PERCENT)}
</Typography>
</Stack>
<Typography variant="body2" component="span" sx={{ opacity: 0.72 }}>
&nbsp;than last month
</Typography>
</div>
</Stack>
<ReactApexChart type="area" series={CHART_DATA} options={chartOptions} height={100} />
</RootStyle>
);
}

View File

@@ -1,9 +1,31 @@
import numeral from 'numeral';
// ----------------------------------------------------------------------
// load a locale
numeral.register('locale', 'id', {
delimiters: {
thousands: '.',
decimal: ','
},
abbreviations: {
thousand: 'k',
million: 'm',
billion: 'b',
trillion: 't'
},
ordinal : function (number: number) {
return number === 1 ? 'er' : 'ème';
},
currency: {
symbol: 'Rp '
}
});
// switch between locales
numeral.locale('id');
export function fCurrency(number: string | number) {
return numeral(number).format(Number.isInteger(number) ? '$0,0' : '$0,0.00');
return numeral(number).format('$0,0');
}
export function fPercent(number: number) {