Separate Client Portal & Dashboard
This commit is contained in:
18
frontend/dashboard/src/hooks/useAuth.ts
Normal file
18
frontend/dashboard/src/hooks/useAuth.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { useContext } from 'react';
|
||||
//
|
||||
import { AuthContext } from '../contexts/LaravelAuthContext';
|
||||
// import { AuthContext } from '../contexts/Auth0Context';
|
||||
// import { AuthContext } from '../contexts/FirebaseContext';
|
||||
// import { AuthContext } from '../contexts/AwsCognitoContext';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const useAuth = () => {
|
||||
const context = useContext(AuthContext);
|
||||
|
||||
if (!context) throw new Error('Auth context must be use inside AuthProvider');
|
||||
|
||||
return context;
|
||||
};
|
||||
|
||||
export default useAuth;
|
||||
8
frontend/dashboard/src/hooks/useCollapseDrawer.ts
Normal file
8
frontend/dashboard/src/hooks/useCollapseDrawer.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { useContext } from 'react';
|
||||
import { CollapseDrawerContext } from '../contexts/CollapseDrawerContext';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const useCollapseDrawer = () => useContext(CollapseDrawerContext);
|
||||
|
||||
export default useCollapseDrawer;
|
||||
16
frontend/dashboard/src/hooks/useIsMountedRef.ts
Normal file
16
frontend/dashboard/src/hooks/useIsMountedRef.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { useRef, useEffect } from 'react';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function useIsMountedRef() {
|
||||
const isMounted = useRef(true);
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
isMounted.current = false;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return isMounted;
|
||||
}
|
||||
33
frontend/dashboard/src/hooks/useLocalStorage.ts
Normal file
33
frontend/dashboard/src/hooks/useLocalStorage.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function useLocalStorage<ValueType>(key: string, defaultValue: ValueType) {
|
||||
const [value, setValue] = useState(() => {
|
||||
const storedValue = localStorage.getItem(key);
|
||||
return storedValue === null ? defaultValue : JSON.parse(storedValue);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const listener = (e: StorageEvent) => {
|
||||
if (e.storageArea === localStorage && e.key === key) {
|
||||
setValue(e.newValue ? JSON.parse(e.newValue) : e.newValue);
|
||||
}
|
||||
};
|
||||
window.addEventListener('storage', listener);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('storage', listener);
|
||||
};
|
||||
}, [key, defaultValue]);
|
||||
|
||||
const setValueInLocalStorage = (newValue: ValueType) => {
|
||||
setValue((currentValue: any) => {
|
||||
const result = typeof newValue === 'function' ? newValue(currentValue) : newValue;
|
||||
localStorage.setItem(key, JSON.stringify(result));
|
||||
return result;
|
||||
});
|
||||
};
|
||||
|
||||
return [value, setValueInLocalStorage];
|
||||
}
|
||||
43
frontend/dashboard/src/hooks/useLocales.ts
Normal file
43
frontend/dashboard/src/hooks/useLocales.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
// @mui
|
||||
import { enUS, deDE, frFR } from '@mui/material/locale';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const LANGS = [
|
||||
{
|
||||
label: 'English',
|
||||
value: 'en',
|
||||
systemValue: enUS,
|
||||
icon: 'https://minimal-assets-api.vercel.app/assets/icons/ic_flag_en.svg',
|
||||
},
|
||||
{
|
||||
label: 'German',
|
||||
value: 'de',
|
||||
systemValue: deDE,
|
||||
icon: 'https://minimal-assets-api.vercel.app/assets/icons/ic_flag_de.svg',
|
||||
},
|
||||
{
|
||||
label: 'French',
|
||||
value: 'fr',
|
||||
systemValue: frFR,
|
||||
icon: 'https://minimal-assets-api.vercel.app/assets/icons/ic_flag_fr.svg',
|
||||
},
|
||||
];
|
||||
|
||||
export default function useLocales() {
|
||||
const { i18n, t: translate } = useTranslation();
|
||||
const langStorage = localStorage.getItem('i18nextLng');
|
||||
const currentLang = LANGS.find((_lang) => _lang.value === langStorage) || LANGS[1];
|
||||
|
||||
const handleChangeLanguage = (newlang: string) => {
|
||||
i18n.changeLanguage(newlang);
|
||||
};
|
||||
|
||||
return {
|
||||
onChangeLang: handleChangeLanguage,
|
||||
translate,
|
||||
currentLang,
|
||||
allLang: LANGS,
|
||||
};
|
||||
}
|
||||
26
frontend/dashboard/src/hooks/useOffSetTop.ts
Normal file
26
frontend/dashboard/src/hooks/useOffSetTop.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function useOffSetTop(top: number) {
|
||||
const [offsetTop, setOffSetTop] = useState(false);
|
||||
const isTop = top || 100;
|
||||
|
||||
useEffect(() => {
|
||||
window.onscroll = () => {
|
||||
if (window.pageYOffset > isTop) {
|
||||
setOffSetTop(true);
|
||||
} else {
|
||||
setOffSetTop(false);
|
||||
}
|
||||
};
|
||||
return () => {
|
||||
window.onscroll = null;
|
||||
};
|
||||
}, [isTop]);
|
||||
|
||||
return offsetTop;
|
||||
}
|
||||
|
||||
// Usage
|
||||
// const offset = useOffSetTop(100);
|
||||
39
frontend/dashboard/src/hooks/useResponsive.ts
Normal file
39
frontend/dashboard/src/hooks/useResponsive.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
// @mui
|
||||
import { Breakpoint } from '@mui/material';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type Query = 'up' | 'down' | 'between' | 'only';
|
||||
type Key = Breakpoint | number;
|
||||
type Start = Breakpoint | number;
|
||||
type End = Breakpoint | number;
|
||||
|
||||
export default function useResponsive(query: Query, key?: Key, start?: Start, end?: End) {
|
||||
const theme = useTheme();
|
||||
|
||||
const mediaUp = useMediaQuery(theme.breakpoints.up(key as Key));
|
||||
|
||||
const mediaDown = useMediaQuery(theme.breakpoints.down(key as Key));
|
||||
|
||||
const mediaBetween = useMediaQuery(theme.breakpoints.between(start as Start, end as End));
|
||||
|
||||
const mediaOnly = useMediaQuery(theme.breakpoints.only(key as Breakpoint));
|
||||
|
||||
if (query === 'up') {
|
||||
return mediaUp;
|
||||
}
|
||||
|
||||
if (query === 'down') {
|
||||
return mediaDown;
|
||||
}
|
||||
|
||||
if (query === 'between') {
|
||||
return mediaBetween;
|
||||
}
|
||||
|
||||
if (query === 'only') {
|
||||
return mediaOnly;
|
||||
}
|
||||
}
|
||||
8
frontend/dashboard/src/hooks/useSettings.ts
Normal file
8
frontend/dashboard/src/hooks/useSettings.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { useContext } from 'react';
|
||||
import { SettingsContext } from '../contexts/SettingsContext';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const useSettings = () => useContext(SettingsContext);
|
||||
|
||||
export default useSettings;
|
||||
138
frontend/dashboard/src/hooks/useTable.ts
Normal file
138
frontend/dashboard/src/hooks/useTable.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export type UseTableProps = {
|
||||
dense: boolean;
|
||||
page: number;
|
||||
setPage: React.Dispatch<React.SetStateAction<number>>;
|
||||
rowsPerPage: number;
|
||||
order: 'asc' | 'desc';
|
||||
orderBy: string;
|
||||
//
|
||||
selected: string[];
|
||||
setSelected: React.Dispatch<React.SetStateAction<string[]>>;
|
||||
onSelectRow: (id: string) => void;
|
||||
onSelectAllRows: (checked: boolean, newSelecteds: string[]) => void;
|
||||
//
|
||||
onSort: (id: string) => void;
|
||||
onChangePage: (event: unknown, newPage: number) => void;
|
||||
onChangeRowsPerPage: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
onChangeDense: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
};
|
||||
|
||||
export type Props = {
|
||||
defaultDense?: boolean;
|
||||
defaultOrder?: 'asc' | 'desc';
|
||||
defaultOrderBy?: string;
|
||||
defaultSelected?: string[];
|
||||
defaultRowsPerPage?: number;
|
||||
defaultCurrentPage?: number;
|
||||
};
|
||||
|
||||
export default function useTable(props?: Props) {
|
||||
const [dense, setDense] = useState(props?.defaultDense || false);
|
||||
|
||||
const [orderBy, setOrderBy] = useState(props?.defaultOrderBy || 'name');
|
||||
|
||||
const [order, setOrder] = useState<'asc' | 'desc'>(props?.defaultOrder || 'asc');
|
||||
|
||||
const [page, setPage] = useState(props?.defaultCurrentPage || 0);
|
||||
|
||||
const [rowsPerPage, setRowsPerPage] = useState(props?.defaultRowsPerPage || 5);
|
||||
|
||||
const [selected, setSelected] = useState<string[]>(props?.defaultSelected || []);
|
||||
|
||||
const onSort = (id: string) => {
|
||||
const isAsc = orderBy === id && order === 'asc';
|
||||
if (id !== '') {
|
||||
setOrder(isAsc ? 'desc' : 'asc');
|
||||
setOrderBy(id);
|
||||
}
|
||||
};
|
||||
|
||||
const onSelectRow = (id: string) => {
|
||||
const selectedIndex = selected.indexOf(id);
|
||||
|
||||
let newSelected: string[] = [];
|
||||
|
||||
if (selectedIndex === -1) {
|
||||
newSelected = newSelected.concat(selected, id);
|
||||
} else if (selectedIndex === 0) {
|
||||
newSelected = newSelected.concat(selected.slice(1));
|
||||
} else if (selectedIndex === selected.length - 1) {
|
||||
newSelected = newSelected.concat(selected.slice(0, -1));
|
||||
} else if (selectedIndex > 0) {
|
||||
newSelected = newSelected.concat(
|
||||
selected.slice(0, selectedIndex),
|
||||
selected.slice(selectedIndex + 1)
|
||||
);
|
||||
}
|
||||
setSelected(newSelected);
|
||||
};
|
||||
|
||||
const onSelectAllRows = (checked: boolean, newSelecteds: string[]) => {
|
||||
if (checked) {
|
||||
setSelected(newSelecteds);
|
||||
return;
|
||||
}
|
||||
setSelected([]);
|
||||
};
|
||||
|
||||
const onChangePage = (event: unknown, newPage: number) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
|
||||
const onChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setRowsPerPage(parseInt(event.target.value, 10));
|
||||
setPage(0);
|
||||
};
|
||||
|
||||
const onChangeDense = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setDense(event.target.checked);
|
||||
};
|
||||
|
||||
return {
|
||||
dense,
|
||||
order,
|
||||
page,
|
||||
setPage,
|
||||
orderBy,
|
||||
rowsPerPage,
|
||||
//
|
||||
selected,
|
||||
setSelected,
|
||||
onSelectRow,
|
||||
onSelectAllRows,
|
||||
//
|
||||
onSort,
|
||||
onChangePage,
|
||||
onChangeDense,
|
||||
onChangeRowsPerPage,
|
||||
};
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export function descendingComparator<T>(a: T, b: T, orderBy: keyof T) {
|
||||
if (b[orderBy] < a[orderBy]) {
|
||||
return -1;
|
||||
}
|
||||
if (b[orderBy] > a[orderBy]) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function getComparator<Key extends keyof any>(
|
||||
order: 'asc' | 'desc',
|
||||
orderBy: Key
|
||||
): (a: { [key in Key]: number | string }, b: { [key in Key]: number | string }) => number {
|
||||
return order === 'desc'
|
||||
? (a, b) => descendingComparator(a, b, orderBy)
|
||||
: (a, b) => -descendingComparator(a, b, orderBy);
|
||||
}
|
||||
|
||||
export function emptyRows(page: number, rowsPerPage: number, arrayLength: number) {
|
||||
return page > 0 ? Math.max(0, (1 + page) * rowsPerPage - arrayLength) : 0;
|
||||
}
|
||||
15
frontend/dashboard/src/hooks/useTabs.ts
Normal file
15
frontend/dashboard/src/hooks/useTabs.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function useTabs(defaultValues?: string) {
|
||||
const [currentTab, setCurrentTab] = useState(defaultValues || '');
|
||||
|
||||
return {
|
||||
currentTab,
|
||||
onChangeTab: (event: React.SyntheticEvent<Element, Event>, newValue: any) => {
|
||||
setCurrentTab(newValue);
|
||||
},
|
||||
setCurrentTab,
|
||||
};
|
||||
}
|
||||
15
frontend/dashboard/src/hooks/useToggle.ts
Normal file
15
frontend/dashboard/src/hooks/useToggle.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export default function useToggle(defaultChecked?: boolean) {
|
||||
const [toggle, setToggle] = useState(defaultChecked || false);
|
||||
|
||||
return {
|
||||
toggle,
|
||||
onToggle: () => setToggle(!toggle),
|
||||
onOpen: () => setToggle(true),
|
||||
onClose: () => setToggle(false),
|
||||
setToggle,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user