First Commit

This commit is contained in:
cesnimda
2026-03-21 11:55:27 +01:00
commit 2e8a29b4d0
1757 changed files with 166084 additions and 0 deletions
@@ -0,0 +1,98 @@
'use client';
// @mui
import { useTheme } from '@mui/material/styles';
import Grid from '@mui/material/Grid';
// @project
import OverviewCard from '@/components/cards/OverviewCard';
import { getRadiusStyles } from '@/utils/getRadiusStyles';
// @assets
import { IconArrowDown, IconArrowUp } from '@tabler/icons-react';
/*************************** CARDS - BORDER WITH RADIUS ***************************/
export function applyBorderWithRadius(radius, theme) {
return {
overflow: 'hidden',
'--Grid-borderWidth': '1px',
borderTop: 'var(--Grid-borderWidth) solid',
borderLeft: 'var(--Grid-borderWidth) solid',
borderColor: 'divider',
'& > div': {
overflow: 'hidden',
borderRight: 'var(--Grid-borderWidth) solid',
borderBottom: 'var(--Grid-borderWidth) solid',
borderColor: 'divider',
[theme.breakpoints.down('md')]: {
'&:nth-of-type(1)': getRadiusStyles(radius, 'topLeft'),
'&:nth-of-type(2)': getRadiusStyles(radius, 'topRight'),
'&:nth-of-type(3)': getRadiusStyles(radius, 'bottomLeft'),
'&:nth-of-type(4)': getRadiusStyles(radius, 'bottomRight')
},
[theme.breakpoints.up('md')]: {
'&:first-of-type': getRadiusStyles(radius, 'topLeft', 'bottomLeft'),
'&:last-of-type': getRadiusStyles(radius, 'topRight', 'bottomRight')
}
}
};
}
/*************************** OVERVIEW CARD -DATA ***************************/
const overviewAnalytics = [
{
title: 'Unique Visitors',
value: '23,876',
compare: 'Compare to last week',
chip: {
label: '24.5%',
avatar: <IconArrowUp />
}
},
{
title: 'Page View',
value: '30,450',
compare: 'Compare to last week',
chip: {
label: '20.5%',
avatar: <IconArrowUp />
}
},
{
title: 'Events',
value: '34,789',
compare: 'Compare to last week',
chip: {
label: '20.5%',
color: 'error',
avatar: <IconArrowDown />
}
},
{
title: 'Live Visitor',
value: '45,687',
compare: 'Compare to last week',
chip: {
label: '24.5%',
avatar: <IconArrowUp />
}
}
];
/*************************** OVERVIEW - CARDS ***************************/
export default function AnalyticsOverviewCard() {
const theme = useTheme();
return (
<Grid container sx={{ borderRadius: 4, boxShadow: theme.vars.customShadows.section, ...applyBorderWithRadius(16, theme) }}>
{overviewAnalytics.map((item, index) => (
<Grid key={index} size={{ xs: 6, sm: 6, md: 3 }}>
<OverviewCard {...{ ...item, cardProps: { sx: { border: 'none', borderRadius: 0, boxShadow: 'none' } } }} />
</Grid>
))}
</Grid>
);
}
@@ -0,0 +1,275 @@
'use client';
import { useState } from 'react';
// @mui
import { useTheme } from '@mui/material/styles';
import { LineChart } from '@mui/x-charts/LineChart';
import Stack from '@mui/material/Stack';
import Tab from '@mui/material/Tab';
import Tabs from '@mui/material/Tabs';
import Typography from '@mui/material/Typography';
// @project
import MainCard from '@/components/MainCard';
import Legend from '@/components/third-party/chart/Legend';
import { TabsType, ViewMode } from '@/enum';
/*************************** CHART - DATA ***************************/
const yearlyPoints = [
new Date(2014, 0, 1),
new Date(2014, 2, 1),
new Date(2014, 5, 1),
new Date(2014, 8, 1),
new Date(2014, 11, 1),
new Date(2015, 0, 1),
new Date(2015, 2, 1),
new Date(2015, 5, 1),
new Date(2015, 8, 1),
new Date(2015, 11, 1),
new Date(2016, 0, 1),
new Date(2016, 2, 1),
new Date(2016, 5, 1),
new Date(2016, 8, 1),
new Date(2016, 11, 1),
new Date(2017, 0, 1),
new Date(2017, 2, 1),
new Date(2017, 5, 1),
new Date(2017, 8, 1),
new Date(2017, 11, 1),
new Date(2018, 0, 1),
new Date(2018, 2, 1),
new Date(2018, 5, 1),
new Date(2018, 8, 1),
new Date(2018, 11, 1),
new Date(2019, 0, 1),
new Date(2019, 2, 1),
new Date(2019, 5, 1),
new Date(2019, 8, 1),
new Date(2019, 11, 1),
new Date(2020, 0, 1),
new Date(2020, 2, 1),
new Date(2020, 5, 1),
new Date(2020, 8, 1),
new Date(2020, 11, 1),
new Date(2021, 0, 1),
new Date(2021, 2, 1),
new Date(2021, 5, 1),
new Date(2021, 8, 1),
new Date(2021, 11, 1),
new Date(2022, 0, 1),
new Date(2022, 2, 1),
new Date(2022, 5, 1),
new Date(2022, 8, 1),
new Date(2022, 11, 1),
new Date(2023, 0, 1),
new Date(2023, 2, 1),
new Date(2023, 5, 1),
new Date(2023, 8, 1),
new Date(2023, 11, 1)
];
const yearlyData = {
pageViewData: [
190, 230, 240, 230, 240, 230, 250, 270, 300, 320, 340, 360, 400, 420, 450, 470, 490, 500, 480, 450, 420, 380, 420, 380, 190, 230, 240,
230, 240, 230, 250, 270, 300, 320, 400, 440, 480, 520, 540, 580, 620, 640, 680, 720, 650, 680, 720, 840, 950, 800
],
uniqueVisitorData: [
900, 920, 930, 860, 840, 820, 800, 840, 860, 840, 800, 780, 760, 790, 740, 710, 670, 650, 690, 750, 780, 760, 730, 680, 650, 620, 500,
470, 430, 400, 380, 360, 340, 320, 300, 280, 260, 240, 220, 260, 300, 340, 380, 420, 460, 360, 450, 520, 450, 600
]
};
const monthlyPoints = [
new Date(2023, 0, 1),
new Date(2023, 0, 15),
new Date(2023, 0, 31),
new Date(2023, 1, 1),
new Date(2023, 1, 15),
new Date(2023, 1, 28),
new Date(2023, 2, 1),
new Date(2023, 2, 15),
new Date(2023, 2, 31),
new Date(2023, 3, 1),
new Date(2023, 3, 15),
new Date(2023, 3, 30),
new Date(2023, 4, 1),
new Date(2023, 4, 15),
new Date(2023, 4, 31),
new Date(2023, 5, 1),
new Date(2023, 5, 15),
new Date(2023, 5, 30),
new Date(2023, 6, 1),
new Date(2023, 6, 15),
new Date(2023, 6, 31),
new Date(2023, 7, 1),
new Date(2023, 7, 15),
new Date(2023, 7, 31),
new Date(2023, 8, 1),
new Date(2023, 8, 15),
new Date(2023, 8, 30),
new Date(2023, 9, 1),
new Date(2023, 9, 15),
new Date(2023, 9, 31),
new Date(2023, 10, 1),
new Date(2023, 10, 15),
new Date(2023, 10, 30),
new Date(2023, 11, 1),
new Date(2023, 11, 15),
new Date(2023, 11, 31)
];
const monthlyData = {
pageViewData: [
190, 230, 240, 230, 300, 230, 250, 270, 230, 320, 340, 450, 400, 420, 485, 470, 490, 500, 480, 450, 420, 380, 420, 380, 400, 600, 575,
540, 550, 520, 580, 570, 600, 600, 720, 780
],
uniqueVisitorData: [
900, 920, 930, 860, 840, 820, 800, 840, 860, 840, 800, 780, 760, 790, 740, 710, 670, 650, 690, 750, 780, 760, 730, 680, 650, 680, 630,
510, 460, 460, 405, 460, 415, 430, 410, 500
]
};
const dailyPoints = [
new Date(2024, 0, 1),
new Date(2024, 0, 2),
new Date(2024, 0, 3),
new Date(2024, 0, 4),
new Date(2024, 0, 5),
new Date(2024, 0, 6),
new Date(2024, 0, 7)
];
const dailyData = {
pageViewData: [10, 5, 12, 8, 35, 14, 30],
uniqueVisitorData: [15, 20, 22, 18, 21, 30, 38]
};
const timeFilter = ['Daily', 'Monthly', 'Yearly'];
const valueFormatter = (date, view) => {
switch (view) {
case ViewMode.DAILY:
return date.toLocaleDateString('en-us', { weekday: 'short' });
case ViewMode.MONTHLY:
return date.toLocaleDateString('en-US', { month: 'short' });
case ViewMode.YEARLY:
default:
return date.getFullYear().toString();
}
};
const tickInterval = (date, view) => {
switch (view) {
case ViewMode.MONTHLY:
return date.getDate() === 15;
case ViewMode.YEARLY:
return date.getMonth() === 5;
case ViewMode.DAILY:
default:
return true;
}
};
const dataMap = { [ViewMode.MONTHLY]: monthlyData, [ViewMode.DAILY]: dailyData, [ViewMode.YEARLY]: yearlyData };
/*************************** CHART - 1 ***************************/
export default function Chart1() {
const theme = useTheme();
const [view, setView] = useState(ViewMode.MONTHLY);
const [visibilityOption, setVisibilityOption] = useState({
page_views: true,
unique_visitor: true
});
const handleViewChange = (_event, newValue) => {
setView(newValue);
};
const toggleVisibility = (id) => {
setVisibilityOption((prev) => ({ ...prev, [id]: !prev[id] }));
};
const seriesData = [
{
id: 'page_views',
data: dataMap[view].pageViewData,
color: theme.vars.palette.primary.light,
visible: visibilityOption['page_views'],
label: 'Page View'
},
{
id: 'unique_visitor',
data: dataMap[view].uniqueVisitorData,
color: theme.vars.palette.primary.main,
visible: visibilityOption['unique_visitor'],
label: 'Unique Visitor'
}
];
const visibleSeries = seriesData.filter((s) => s.visible);
const lagendItems = seriesData.map((series) => ({ label: series.label, color: series.color, visible: series.visible, id: series.id }));
const xData = view === ViewMode.MONTHLY ? monthlyPoints : view === ViewMode.DAILY ? dailyPoints : yearlyPoints;
// Dynamic styles for visible series
const dynamicSeriesStyles = visibleSeries.reduce((acc, series) => {
acc[`& .MuiAreaElement-series-${series.id}`] = { fill: `url(#${series.id})`, opacity: series.id === 'page_views' ? 0 : 0.15 };
return acc;
}, {});
return (
<MainCard>
<Stack sx={{ gap: 3 }}>
<Stack direction="row" sx={{ alignItems: 'end', justifyContent: 'space-between', gap: 2, flexWrap: 'wrap' }}>
<Stack sx={{ gap: 0.5 }}>
<Typography variant="h4" sx={{ fontWeight: 400 }}>
Analysis
</Typography>
<Typography variant="caption" sx={{ color: 'grey.700' }}>
Analyze user engagement and improve your product with real-time analytics.
</Typography>
</Stack>
<Tabs value={view} onChange={handleViewChange} aria-label="filter tabs" type={TabsType.SEGMENTED} sx={{ width: 'fit-content' }}>
{timeFilter.map((filter, index) => (
<Tab label={filter} value={filter} key={index} />
))}
</Tabs>
</Stack>
<Legend items={lagendItems} onToggle={toggleVisibility} />
</Stack>
<LineChart
series={visibleSeries.map((series) => ({ ...series, showMark: false, curve: 'linear', area: true }))}
height={261}
grid={{ horizontal: true }}
margin={{ top: 25, right: 0, bottom: -4, left: 0 }}
xAxis={[
{
data: xData,
scaleType: 'point',
disableLine: true,
disableTicks: true,
valueFormatter: (value) => valueFormatter(value, view),
tickInterval: (time) => tickInterval(time, view)
}
]}
yAxis={[{ scaleType: 'linear', disableLine: true, disableTicks: true, label: 'Visits' }]}
hideLegend
sx={{ '& .MuiLineElement-root': { strokeDasharray: '0', strokeWidth: 2 }, ...dynamicSeriesStyles }}
>
<defs>
{visibleSeries.map((series, index) => (
<linearGradient id={series.id} key={index} gradientTransform="rotate(90)">
<stop offset="10%" stopColor={series.color} stopOpacity={1} />
<stop offset="86%" stopColor={series.color} stopOpacity={0.1} />
</linearGradient>
))}
</defs>
</LineChart>
</MainCard>
);
}
@@ -0,0 +1,252 @@
'use client';
import PropTypes from 'prop-types';
import { useState } from 'react';
// @mui
import { useTheme } from '@mui/material/styles';
import Grid from '@mui/material/Grid';
import Stack from '@mui/material/Stack';
import Tab from '@mui/material/Tab';
import Tabs from '@mui/material/Tabs';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
// @project
import ProgressCard from '@/components/cards/ProgressCard';
import { TabsType } from '@/enum';
import { getRadiusStyles } from '@/utils/getRadiusStyles';
/*************************** TABS - DATA ***************************/
const sevenDaysData = [
{ title: 'Direct', value: '16,890', progress: { value: 45 } },
{ title: 'Google.com', value: '4,909', progress: { value: 56 } },
{ title: 'Remix.com', value: '550', progress: { value: 74 } },
{ title: 'dev.to', value: '140', progress: { value: 25 } },
{ title: 'acpc.api.ic.io', value: '8,675', progress: { value: 45 } },
{ title: 'wewe.uv.us', value: '4,900', progress: { value: 95 } }
];
const monthData = [
{ title: 'Direct', value: '67,560', progress: { value: 75 } },
{ title: 'Google.com', value: '19,636', progress: { value: 45 } },
{ title: 'Remix.com', value: '2,220', progress: { value: 10 } },
{ title: 'dev.to', value: '560', progress: { value: 89 } },
{ title: 'acpc.api.ic.io', value: '34,700', progress: { value: 95 } },
{ title: 'wewe.uv.us', value: '19,600', progress: { value: 74 } }
];
const yearData = [
{ title: 'Direct', value: '8,10,720', progress: { value: 52 } },
{ title: 'Google.com', value: '2,35,632', progress: { value: 45 } },
{ title: 'Remix.com', value: '26,640', progress: { value: 85 } },
{ title: 'dev.to', value: '6,720', progress: { value: 42 } },
{ title: 'acpc.api.ic.io', value: '4,16,400', progress: { value: 55 } },
{ title: 'wewe.uv.us', value: '2,35,200', progress: { value: 45 } }
];
const routesData = [
{ title: 'Home', value: '16,890', progress: { value: 15 } },
{ title: 'Pricing', value: '4,909', progress: { value: 78 } },
{ title: 'Change-log', value: '550', progress: { value: 25 } },
{ title: 'Feature', value: '140', progress: { value: 47 } },
{ title: 'Service', value: '8,675', progress: { value: 20 } },
{ title: 'Pricing', value: '4,900', progress: { value: 74 } }
];
const pageData = [
{ title: 'Home', value: '67,560', progress: { value: 45 } },
{ title: 'Pricing', value: '19,636', progress: { value: 25 } },
{ title: 'Change-log', value: '2,220', progress: { value: 74 } },
{ title: 'Feature', value: '560', progress: { value: 44 } },
{ title: 'Service', value: '34,700', progress: { value: 41 } },
{ title: 'Pricing', value: '19,600', progress: { value: 95 } }
];
const affiliateData = [
{ title: 'No-Refference', value: '16,890', progress: { value: 44 } },
{ title: 'Medium', value: '4,909', progress: { value: 90 } },
{ title: 'remaixblock.com', value: '550', progress: { value: 20 } },
{ title: 'remaix-pge-block-hero', value: '140', progress: { value: 85 } },
{ title: 'remaix-pge-block-banner', value: '8,675', progress: { value: 75 } },
{ title: 'dev.io', value: '4,900', progress: { value: 78 } }
];
const campaignData = [
{ title: 'No-Refference', value: '67,560', progress: { value: 25 } },
{ title: 'Medium', value: '19,636', progress: { value: 74 } },
{ title: 'remaixblock.com', value: '2,220', progress: { value: 65 } },
{ title: 'remaix-pge-block-hero', value: '560', progress: { value: 45 } },
{ title: 'remaix-pge-block-banner', value: '34,700', progress: { value: 85 } },
{ title: 'dev.io', value: '19,600', progress: { value: 47 } }
];
const marketingData = [
{ title: 'No-Refference', value: '8,10,720', progress: { value: 41 } },
{ title: 'Medium', value: '2,35,632', progress: { value: 35 } },
{ title: 'remaixblock.com', value: '26,640', progress: { value: 55 } },
{ title: 'remaix-pge-block-hero', value: '6,720', progress: { value: 75 } },
{ title: 'remaix-pge-block-banner', value: '4,16,400', progress: { value: 100 } },
{ title: 'dev.io', value: '2,35,200', progress: { value: 20 } }
];
/*************************** TABS - A11Y ***************************/
function a11yProps(value) {
return { value: value, id: `simple-tab-${value}`, 'aria-controls': `simple-tabpanel-${value}` };
}
/*************************** TABS - PANEL ***************************/
function TabPanel({ children, value, index, ...other }) {
return (
<div role="tabpanel" hidden={value !== index} id={`simple-tabpanel-${index}`} aria-labelledby={`simple-tab-${index}`} {...other}>
{value === index && <Box sx={{ pt: 1.5 }}>{children}</Box>}
</div>
);
}
/*************************** TABS - CONTENT ***************************/
function TabContent({ data }) {
return (
<Stack sx={{ gap: 1.25 }}>
{data.map((item, index) => (
<ProgressCard key={index} {...item} />
))}
</Stack>
);
}
/*************************** CARDS - BORDER WITH RADIUS ***************************/
export function applyBorderWithRadius(radius, theme) {
return {
overflow: 'hidden',
'--Grid-borderWidth': '1px',
borderTop: 'var(--Grid-borderWidth) solid',
borderLeft: 'var(--Grid-borderWidth) solid',
borderColor: 'divider',
'& > div': {
overflow: 'hidden',
borderRight: 'var(--Grid-borderWidth) solid',
borderBottom: 'var(--Grid-borderWidth) solid',
borderColor: 'divider',
[theme.breakpoints.only('xs')]: {
'&:first-of-type': getRadiusStyles(radius, 'topLeft', 'topRight'),
'&:last-of-type': getRadiusStyles(radius, 'bottomLeft', 'bottomRight')
},
[theme.breakpoints.between('sm', 'md')]: {
'&:nth-of-type(1)': getRadiusStyles(radius, 'topLeft'),
'&:nth-of-type(2)': getRadiusStyles(radius, 'topRight'),
'&:nth-of-type(3)': getRadiusStyles(radius, 'bottomLeft', 'bottomRight')
},
[theme.breakpoints.up('md')]: {
'&:first-of-type': getRadiusStyles(radius, 'topLeft', 'bottomLeft'),
'&:last-of-type': getRadiusStyles(radius, 'topRight', 'bottomRight')
}
}
};
}
/*************************** CARDS - TOP REFERRERS ***************************/
export default function TopReferrers() {
const theme = useTheme();
const [httpReferrers, setHttpReferrers] = useState('days');
const [pages, setPages] = useState('routes');
const [sources, setSources] = useState('affiliate');
// Separate handleChange functions
const handleHTTPReferrers = (event, newValue) => {
setHttpReferrers(newValue);
};
const handlePages = (event, newValue) => {
setPages(newValue);
};
const handleSources = (event, newValue) => {
setSources(newValue);
};
return (
<>
<Grid container sx={{ borderRadius: 4, boxShadow: theme.vars.customShadows.section, ...applyBorderWithRadius(16, theme) }}>
<Grid size={{ xs: 12, sm: 6, md: 4 }}>
<Stack sx={{ gap: 2.5, p: 3 }}>
<Typography variant="subtitle1">Top HTTP Referrers</Typography>
<Box>
<Tabs
variant="fullWidth"
value={httpReferrers}
onChange={handleHTTPReferrers}
aria-label="basic tabs example"
type={TabsType.SEGMENTED}
>
<Tab label="Last 7 days" {...a11yProps('days')} />
<Tab label="Last Month" {...a11yProps('month')} />
<Tab label="Last Year" {...a11yProps('year')} />
</Tabs>
<TabPanel value={httpReferrers} index="days">
<TabContent data={sevenDaysData} />
</TabPanel>
<TabPanel value={httpReferrers} index="month">
<TabContent data={monthData} />
</TabPanel>
<TabPanel value={httpReferrers} index="year">
<TabContent data={yearData} />
</TabPanel>
</Box>
</Stack>
</Grid>
<Grid size={{ xs: 12, sm: 6, md: 4 }}>
<Stack sx={{ gap: 2.5, p: 3 }}>
<Typography variant="subtitle1">Top Pages</Typography>
<Box>
<Tabs variant="fullWidth" value={pages} onChange={handlePages} aria-label="basic tabs example" type={TabsType.SEGMENTED}>
<Tab label="Routes" {...a11yProps('routes')} />
<Tab label="Pages" {...a11yProps('pages')} />
</Tabs>
<TabPanel value={pages} index="routes">
<TabContent data={routesData} />
</TabPanel>
<TabPanel value={pages} index="pages">
<TabContent data={pageData} />
</TabPanel>
</Box>
</Stack>
</Grid>
<Grid size={{ xs: 12, md: 4 }}>
<Stack sx={{ gap: 2.5, p: 3 }}>
<Typography variant="subtitle1">Top Sources</Typography>
<Box>
<Tabs variant="fullWidth" value={sources} onChange={handleSources} aria-label="basic tabs example" type={TabsType.SEGMENTED}>
<Tab label="Affiliate" {...a11yProps('affiliate')} />
<Tab label="Campaign" {...a11yProps('campaign')} />
<Tab label="Marketing" {...a11yProps('marketing')} />
</Tabs>
<TabPanel value={sources} index="affiliate">
<TabContent data={affiliateData} />
</TabPanel>
<TabPanel value={sources} index="campaign">
<TabContent data={campaignData} />
</TabPanel>
<TabPanel value={sources} index="marketing">
<TabContent data={marketingData} />
</TabPanel>
</Box>
</Stack>
</Grid>
</Grid>
</>
);
}
TabPanel.propTypes = {
children: PropTypes.any,
value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
index: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
other: PropTypes.any
};
TabContent.propTypes = { data: PropTypes.array };