Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ Looking for even more features? Check out SaasAble's [premium version](https://m

## Technology Stack

- React 18
- React 19
- Next js
- TypeScript
- Material UI v7
Expand Down
2 changes: 1 addition & 1 deletion admin/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## Version
NEXT_PUBLIC_VERSION=v1.1.0
NEXT_PUBLIC_VERSION=v1.2.0

## Public URL
NEXT_PUBLIC_PATH=
Expand Down
1,038 changes: 455 additions & 583 deletions admin/package-lock.json

Large diffs are not rendered by default.

29 changes: 13 additions & 16 deletions admin/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "saas-able-react-mui-admin-next-seed-js",
"version": "1.1.0",
"version": "1.2.0",
"private": true,
"author": {
"email": "phoenixcoded@gmail.com",
Expand All @@ -19,17 +19,17 @@
"@emotion/cache": "11.14.0",
"@emotion/react": "11.14.0",
"@emotion/styled": "11.14.0",
"@mui/material": "7.0.1",
"@mui/material-nextjs": "7.0.0",
"@mui/material": "7.0.2",
"@mui/material-nextjs": "7.0.2",
"@mui/x-charts": "7.28.0",
"@mui/x-date-pickers": "7.28.2",
"@mui/x-date-pickers": "7.28.3",
"@tabler/icons-react": "3.31.0",
"lodash-es": "4.17.21",
"next": "15.2.4",
"next": "15.3.0",
"notistack": "3.0.2",
"react": "18.3.1",
"react": "19.1.0",
"react-device-detect": "2.2.3",
"react-dom": "18.3.1",
"react-dom": "19.1.0",
"react-hook-form": "7.55.0",
"simplebar-react": "3.3.0",
"stylis": "4.3.6",
Expand All @@ -38,15 +38,12 @@
},
"devDependencies": {
"@eslint/eslintrc": "3.3.1",
"@eslint/js": "9.23.0",
"eslint": "9.23.0",
"eslint-config-next": "15.2.4",
"eslint-config-prettier": "10.1.1",
"eslint-plugin-prettier": "5.2.5",
"knip": "5.46.4",
"@eslint/js": "9.24.0",
"eslint": "9.24.0",
"eslint-config-next": "15.3.0",
"eslint-config-prettier": "10.1.2",
"eslint-plugin-prettier": "5.2.6",
"knip": "5.50.4",
"prettier": "3.5.3"
},
"resolutions": {
"punycode": "2.3.1"
}
}
32 changes: 13 additions & 19 deletions admin/src/components/MainCard.jsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
'use client';
import PropTypes from 'prop-types';

import { forwardRef } from 'react';

// @mui
import { useTheme } from '@mui/material/styles';
import Card from '@mui/material/Card';

function MainCard({ children, sx = {}, ...others }, ref) {
const theme = useTheme();
export default function MainCard({ children, sx = {}, ref, ...others }) {
const defaultSx = (theme) => ({
p: { xs: 1.75, sm: 2.25, md: 3 },
border: `1px solid ${theme.palette.divider}`,
borderRadius: 4,
boxShadow: theme.customShadows.section
});

const combinedSx = (theme) => ({
...defaultSx(theme),
...(typeof sx === 'function' ? sx(theme) : sx)
});

return (
<Card
ref={ref}
elevation={0}
sx={{
p: { xs: 1.75, sm: 2.25, md: 3 },
border: `1px solid ${theme.palette.divider}`,
borderRadius: 4,
boxShadow: theme.customShadows.section,
...sx
}}
{...others}
>
<Card ref={ref} elevation={0} sx={combinedSx} {...others}>
{children}
</Card>
);
}

export default forwardRef(MainCard);

MainCard.propTypes = { children: PropTypes.any, sx: PropTypes.object, others: PropTypes.any };
6 changes: 1 addition & 5 deletions admin/src/components/header/empty-state/EmptySearch.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
'use client';

import { forwardRef } from 'react';

// @mui
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
Expand All @@ -12,7 +10,7 @@ import { DumpingDoodle } from '@/images/illustration';

/*************************** HEADER - EMPTY SEARCH ***************************/

function EmptySearch(props, ref) {
export default function EmptySearch(props, ref) {
return (
<Stack ref={ref} {...props} sx={{ width: 1, alignItems: 'center', justifyContent: 'center', textAlign: 'center', gap: 1.5, p: 1.5 }}>
<Box sx={{ width: 230, height: 170 }}>
Expand All @@ -29,5 +27,3 @@ function EmptySearch(props, ref) {
</Stack>
);
}

export default forwardRef(EmptySearch);
2 changes: 1 addition & 1 deletion admin/src/components/logo/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function LogoSection({ isIcon, sx, to }) {
const theme = useTheme();

return (
<NextLink href={!to ? APP_DEFAULT_PATH : to} passHref legacyBehavior>
<NextLink href={!to ? APP_DEFAULT_PATH : to} passHref>
<ButtonBase disableRipple sx={{ ...sx, '&:focus-visible': generateFocusStyle(theme.palette.primary.main) }} aria-label="logo">
{isIcon ? <LogoIcon /> : <LogoMain />}
</ButtonBase>
Expand Down
2 changes: 1 addition & 1 deletion admin/src/contexts/ConfigContext.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const ConfigContext = createContext(initialState);
function ConfigProvider({ children }) {
const [config] = useLocalStorage('sass-able-react-mui-admin-next-ts', initialState);

return <ConfigContext.Provider value={{ ...config }}>{children}</ConfigContext.Provider>;
return <ConfigContext value={{ ...config }}>{children}</ConfigContext>;
}

export { ConfigProvider, ConfigContext };
Expand Down
4 changes: 2 additions & 2 deletions admin/src/hooks/useConfig.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useContext } from 'react';
import { use } from 'react';

// @project
import { ConfigContext } from '@/contexts/ConfigContext';
Expand All @@ -17,5 +17,5 @@ import { ConfigContext } from '@/contexts/ConfigContext';
*/

export default function useConfig() {
return useContext(ConfigContext);
return use(ConfigContext);
}
119 changes: 4 additions & 115 deletions admin/src/layouts/AdminLayout/Drawer/DrawerContent/NavCard.jsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
import PropTypes from 'prop-types';
import { useState } from 'react';

// @next
import Link from 'next/link';

// @mui
import { useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery';
import Avatar from '@mui/material/Avatar';
import Button from '@mui/material/Button';
import ClickAwayListener from '@mui/material/ClickAwayListener';
import Grow from '@mui/material/Grow';
import IconButton from '@mui/material/IconButton';
import ListItemAvatar from '@mui/material/ListItemAvatar';
import ListItemIcon from '@mui/material/ListItemIcon';
import Popper from '@mui/material/Popper';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';

// @project
import { DRAWER_WIDTH } from '@/config';
import LogoSection from '@/components/logo';
import MainCard from '@/components/MainCard';
import SimpleBar from '@/components/third-party/SimpleBar';
import { AvatarSize } from '@/enum';

// @assets
Expand All @@ -37,26 +25,6 @@ const data = {
icon: <IconBolt size={16} />
};

/*************************** POPPER - ARROW ***************************/

const popperArrowStyles = (theme) => ({
content: '""',
display: 'block',
position: 'absolute',
bottom: 20,
left: -6,
width: 10,
height: 10,
bgcolor: 'grey.50',
transform: 'translateY(-50%) rotate(45deg)',
zIndex: 120,
borderLeft: '1px solid',
borderLeftColor: 'divider',
borderBottom: '1px solid',
borderBottomColor: 'divider',
boxShadow: theme.customShadows.tooltip
});

/*************************** NAVIGATION CARD - CONTENT ***************************/

function CardContent({ title, description, icon }) {
Expand Down Expand Up @@ -90,91 +58,12 @@ function CardContent({ title, description, icon }) {

/*************************** DRAWER CONTENT - NAVIGATION CARD ***************************/

export default function NavCard({ isMiniDrawer }) {
const theme = useTheme();
const upMD = useMediaQuery(theme.breakpoints.up('md'));

const [anchorEl, setAnchorEl] = useState(null);
const [miniMenuOpened, setMiniMenuOpened] = useState(false);

const handleClick = (event) => {
setAnchorEl(event.currentTarget);
setMiniMenuOpened((prev) => !prev);
};

const handleClose = () => {
setMiniMenuOpened(false);
};

export default function NavCard() {
return (
<>
{!isMiniDrawer ? (
<MainCard sx={{ p: 1.5, bgcolor: 'grey.50', boxShadow: 'none', mb: 3 }}>
<CardContent title={data.title} description={data.description} icon={data.icon} />
</MainCard>
) : (
<IconButton sx={{ marginX: 'auto', mb: 3 }} onMouseEnter={handleClick} onMouseLeave={handleClose} aria-label="upgrade plan">
<ListItemAvatar
sx={{
minWidth: 32,
width: 42,
height: 42,
borderRadius: 2,
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
bgcolor: 'primary.main',
'&:hover': { bgcolor: 'primary.dark' }
}}
>
<ListItemIcon sx={{ minWidth: 0 }}>
<IconBolt size={20} color="background" />
</ListItemIcon>
</ListItemAvatar>
{upMD && (
<Popper
open={miniMenuOpened}
anchorEl={anchorEl}
placement="right-end"
sx={{
zIndex: 1202,
minWidth: 220,
maxWidth: `${DRAWER_WIDTH - 24}px`,
'& > .MuiPaper-root': { position: 'relative', mb: -0.75, '&:before': { ...popperArrowStyles(theme) } }
}}
>
{({ TransitionProps }) => (
<Grow in={miniMenuOpened} {...TransitionProps} timeout={{ appear: 0, enter: 150, exit: 150 }}>
<MainCard
sx={{
p: 1.5,
bgcolor: 'grey.50',
boxShadow: theme.customShadows.tooltip,
backgroundImage: 'none',
transformOrigin: '0 0 0',
left: 16,
overflow: 'visible'
}}
>
<ClickAwayListener onClickAway={handleClose} onMouseEnter={handleClick} onMouseLeave={handleClose}>
<Box>
<SimpleBar style={{ maxHeight: '50vh', overflowX: 'hidden', overflowY: 'auto' }}>
<CardContent title={data.title} description={data.description} icon={data.icon} />
</SimpleBar>
</Box>
</ClickAwayListener>
</MainCard>
</Grow>
)}
</Popper>
)}
</IconButton>
)}
</>
<MainCard sx={{ p: 1.5, bgcolor: 'grey.50', boxShadow: 'none', mb: 3 }}>
<CardContent title={data.title} description={data.description} icon={data.icon} />
</MainCard>
);
}

CardContent.propTypes = { title: PropTypes.string, description: PropTypes.string, icon: PropTypes.any };

NavCard.propTypes = { isMiniDrawer: PropTypes.bool };
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function DrawerContent() {
<SimpleBar sx={{ height: contentHeight }}>
<Stack sx={{ minHeight: contentHeight, px: !drawerOpen && upMD ? 0 : 2, justifyContent: 'space-between' }}>
<ResponsiveDrawer />
<NavCard isMiniDrawer={!drawerOpen && upMD} />
<NavCard />
</Stack>
</SimpleBar>
);
Expand Down
2 changes: 1 addition & 1 deletion uikit/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## Version
NEXT_PUBLIC_VERSION=v1.1.0
NEXT_PUBLIC_VERSION=v1.2.0

## Public URL
NEXT_PUBLIC_PATH=
Expand Down
Loading