Compare commits
5 Commits
317617c3ce
...
15f9ae928c
| Author | SHA1 | Date | |
|---|---|---|---|
| 15f9ae928c | |||
| 6983d5724a | |||
| 36cb82d335 | |||
| 993bf970d1 | |||
| 0db5333242 |
@@ -1,11 +0,0 @@
|
|||||||
/**
|
|
||||||
* Authorization Roles
|
|
||||||
*/
|
|
||||||
const authRoles = {
|
|
||||||
admin: ['admin'],
|
|
||||||
staff: ['admin', 'staff'],
|
|
||||||
user: ['admin', 'staff', 'user'],
|
|
||||||
onlyGuest: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
export default authRoles;
|
|
||||||
19
src/app/configs/consts.js
Normal file
19
src/app/configs/consts.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
export const STATISTICS_MODES = {
|
||||||
|
positive: 'positive',
|
||||||
|
extra_positive: 'extra_positive',
|
||||||
|
negative: 'negative',
|
||||||
|
extra_negative: 'extra_negative',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PROPERTIES_LAYOUTS = {
|
||||||
|
list: 'list',
|
||||||
|
grid: 'grid',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Authorization Roles
|
||||||
|
export const authRoles = {
|
||||||
|
admin: ['admin'],
|
||||||
|
staff: ['admin', 'staff'],
|
||||||
|
user: ['admin', 'staff', 'user'],
|
||||||
|
onlyGuest: [],
|
||||||
|
};
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
|
|
||||||
import ForgotPasswordPage from './ForgotPasswordPage';
|
import ForgotPasswordPage from './ForgotPasswordPage';
|
||||||
import authRoles from '../../../configs/authRoles';
|
import authRoles from '../../../configs/consts';
|
||||||
import en from './i18n/en';
|
import en from './i18n/en';
|
||||||
|
|
||||||
i18next.addResourceBundle('en', 'forgotPasswordPage', en);
|
i18next.addResourceBundle('en', 'forgotPasswordPage', en);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
|
|
||||||
import SignInPage from './SignInPage';
|
import SignInPage from './SignInPage';
|
||||||
import authRoles from '../../../configs/authRoles';
|
import authRoles from '../../../configs/consts';
|
||||||
import en from './i18n/en';
|
import en from './i18n/en';
|
||||||
|
|
||||||
i18next.addResourceBundle('en', 'signInPage', en);
|
i18next.addResourceBundle('en', 'signInPage', en);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
|
|
||||||
import SignUpPage from './SignUpPage';
|
import SignUpPage from './SignUpPage';
|
||||||
import authRoles from '../../../configs/authRoles';
|
import authRoles from '../../../configs/consts';
|
||||||
import en from './i18n/en';
|
import en from './i18n/en';
|
||||||
|
|
||||||
i18next.addResourceBundle('en', 'signUpPage', en);
|
i18next.addResourceBundle('en', 'signUpPage', en);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
|
|
||||||
import authRoles from '../../../configs/authRoles';
|
import authRoles from '../../../configs/consts';
|
||||||
import Dashboard from './Dashboard';
|
import Dashboard from './Dashboard';
|
||||||
import en from './i18n/en';
|
import en from './i18n/en';
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
import { styled } from '@mui/material/styles';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import FusePageSimple from '@fuse/core/FusePageSimple';
|
import FusePageSimple from '@fuse/core/FusePageSimple';
|
||||||
import DemoContent from '@fuse/core/DemoContent';
|
import { Paper } from '@mui/material';
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
|
import { PROPERTIES_LAYOUTS } from 'app/configs/consts';
|
||||||
|
import { selectUserFavorites, updateUserFavorites } from 'app/store/userSlice';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { useCallback, useMemo } from 'react';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { usePropertiesHeader } from 'src/app/hooks';
|
||||||
|
import PropertiesHeader from '../shared-components/PropertiesHeader';
|
||||||
|
import PropertyGridCard from '../shared-components/PropertyGridCard';
|
||||||
|
import PropertyListItem from '../shared-components/PropertyListItem';
|
||||||
|
|
||||||
const Root = styled(FusePageSimple)(({ theme }) => ({
|
const Root = styled(FusePageSimple)(({ theme }) => ({
|
||||||
'& .FusePageSimple-header': {
|
'& .FusePageSimple-header': {
|
||||||
@@ -16,21 +24,73 @@ const Root = styled(FusePageSimple)(({ theme }) => ({
|
|||||||
'& .FusePageSimple-sidebarContent': {},
|
'& .FusePageSimple-sidebarContent': {},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function FavoritesPage(props) {
|
function FavoritesPage() {
|
||||||
const { t } = useTranslation('favoritesPage');
|
const dispatch = useDispatch();
|
||||||
|
const items = useSelector(selectUserFavorites);
|
||||||
|
|
||||||
|
const { categories, activeCategory, onCategory, layouts, activeLayout, onLayout, onItemDelete } =
|
||||||
|
usePropertiesHeader(items);
|
||||||
|
|
||||||
|
const onFavorite = useCallback(
|
||||||
|
(id) => {
|
||||||
|
const targetItem = items.find((item) => item.id === id);
|
||||||
|
if (!targetItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onItemDelete(targetItem?.category);
|
||||||
|
dispatch(updateUserFavorites(targetItem)).catch((error) => console.log(error));
|
||||||
|
},
|
||||||
|
[items, onItemDelete, dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderedItems = useMemo(
|
||||||
|
() =>
|
||||||
|
items.map((item, idx) => {
|
||||||
|
if (activeCategory !== 'all' && item.category !== activeCategory) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line consistent-return
|
||||||
|
return activeLayout === PROPERTIES_LAYOUTS.list ? (
|
||||||
|
<PropertyListItem
|
||||||
|
{...item}
|
||||||
|
key={item.title + idx}
|
||||||
|
onDelete={onFavorite}
|
||||||
|
onFavorite={onFavorite}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<PropertyGridCard
|
||||||
|
{...item}
|
||||||
|
key={item.title + idx}
|
||||||
|
onDelete={onFavorite}
|
||||||
|
onFavorite={onFavorite}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
[items, activeCategory, activeLayout, onFavorite]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Root
|
<Root
|
||||||
// header={
|
|
||||||
// <div className="p-24">
|
|
||||||
// <h4>{t('TITLE')}</h4>
|
|
||||||
// </div>
|
|
||||||
// }
|
|
||||||
content={
|
content={
|
||||||
<div className="p-24">
|
<div className="w-full p-60">
|
||||||
<h4>Content</h4>
|
<Paper className="w-full h-320 mb-[30px] rounded-20 shadow-light" />
|
||||||
<br />
|
<PropertiesHeader
|
||||||
<DemoContent />
|
className="mb-40"
|
||||||
|
categories={categories}
|
||||||
|
layouts={layouts}
|
||||||
|
onCategory={onCategory}
|
||||||
|
onLayout={onLayout}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'w-full flex flex-wrap justify-center gap-28',
|
||||||
|
activeLayout === PROPERTIES_LAYOUTS.list && 'flex-col'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{renderedItems}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
scroll="content"
|
scroll="content"
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
|
import { lazy } from 'react';
|
||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
|
|
||||||
import authRoles from '../../../configs/authRoles';
|
import authRoles from '../../../configs/consts';
|
||||||
import Favorites from './Favorites';
|
|
||||||
import en from './i18n/en';
|
import en from './i18n/en';
|
||||||
|
|
||||||
i18next.addResourceBundle('en', 'favoritesPage', en);
|
i18next.addResourceBundle('en', 'favoritesPage', en);
|
||||||
|
|
||||||
|
const Favorites = lazy(() => import('./Favorites'));
|
||||||
|
|
||||||
const FavoritesConfig = {
|
const FavoritesConfig = {
|
||||||
settings: {
|
settings: {
|
||||||
layout: {
|
layout: {
|
||||||
@@ -22,28 +24,3 @@ const FavoritesConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default FavoritesConfig;
|
export default FavoritesConfig;
|
||||||
|
|
||||||
/**
|
|
||||||
* Lazy load Example
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const Example = lazy(() => import('./Example'));
|
|
||||||
|
|
||||||
const ExampleConfig = {
|
|
||||||
settings: {
|
|
||||||
layout: {
|
|
||||||
config: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
routes: [
|
|
||||||
{
|
|
||||||
path: 'example',
|
|
||||||
element: <Example />,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ExampleConfig;
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
import { styled } from '@mui/material/styles';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import FusePageSimple from '@fuse/core/FusePageSimple';
|
import FusePageSimple from '@fuse/core/FusePageSimple';
|
||||||
import DemoContent from '@fuse/core/DemoContent';
|
import { Paper } from '@mui/material';
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
|
import { PROPERTIES_LAYOUTS } from 'app/configs/consts';
|
||||||
|
import { selectUserHistory, updateUserFavorites, updateUserHistory } from 'app/store/userSlice';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { useCallback, useMemo } from 'react';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { usePropertiesHeader } from 'src/app/hooks';
|
||||||
|
import PropertiesHeader from '../shared-components/PropertiesHeader';
|
||||||
|
import PropertyGridCard from '../shared-components/PropertyGridCard';
|
||||||
|
import PropertyListItem from '../shared-components/PropertyListItem';
|
||||||
|
|
||||||
const Root = styled(FusePageSimple)(({ theme }) => ({
|
const Root = styled(FusePageSimple)(({ theme }) => ({
|
||||||
'& .FusePageSimple-header': {
|
'& .FusePageSimple-header': {
|
||||||
@@ -16,21 +24,83 @@ const Root = styled(FusePageSimple)(({ theme }) => ({
|
|||||||
'& .FusePageSimple-sidebarContent': {},
|
'& .FusePageSimple-sidebarContent': {},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function HistoryPage(props) {
|
function HistoryPage() {
|
||||||
const { t } = useTranslation('historyPage');
|
const dispatch = useDispatch();
|
||||||
|
const items = useSelector(selectUserHistory);
|
||||||
|
|
||||||
|
const { categories, activeCategory, onCategory, layouts, activeLayout, onLayout, onItemDelete } =
|
||||||
|
usePropertiesHeader(items);
|
||||||
|
|
||||||
|
const onDelete = useCallback(
|
||||||
|
(id) => {
|
||||||
|
const targetItem = items.find((item) => item.id === id);
|
||||||
|
const newHistory = items.filter((item) => item.id !== id);
|
||||||
|
|
||||||
|
onItemDelete(targetItem?.category);
|
||||||
|
dispatch(updateUserHistory(newHistory));
|
||||||
|
},
|
||||||
|
[items, onItemDelete, dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
const onFavorite = useCallback(
|
||||||
|
(id) => {
|
||||||
|
const targetItem = items.find((item) => item.id === id);
|
||||||
|
if (!targetItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(updateUserFavorites(targetItem)).catch((error) => console.log(error));
|
||||||
|
},
|
||||||
|
[items, dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderedItems = useMemo(
|
||||||
|
() =>
|
||||||
|
items.map((item, idx) => {
|
||||||
|
if (activeCategory !== 'all' && item.category !== activeCategory) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line consistent-return
|
||||||
|
return activeLayout === PROPERTIES_LAYOUTS.list ? (
|
||||||
|
<PropertyListItem
|
||||||
|
{...item}
|
||||||
|
key={item.title + idx}
|
||||||
|
onDelete={onDelete}
|
||||||
|
onFavorite={onFavorite}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<PropertyGridCard
|
||||||
|
{...item}
|
||||||
|
key={item.title + idx}
|
||||||
|
onDelete={onDelete}
|
||||||
|
onFavorite={onFavorite}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
[items, activeCategory, activeLayout, onDelete, onFavorite]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Root
|
<Root
|
||||||
// header={
|
|
||||||
// <div className="p-24">
|
|
||||||
// <h4>{t('TITLE')}</h4>
|
|
||||||
// </div>
|
|
||||||
// }
|
|
||||||
content={
|
content={
|
||||||
<div className="p-24">
|
<div className="w-full p-60">
|
||||||
<h4>Content</h4>
|
<Paper className="w-full h-320 mb-[30px] rounded-20 shadow-light" />
|
||||||
<br />
|
<PropertiesHeader
|
||||||
<DemoContent />
|
className="mb-40"
|
||||||
|
categories={categories}
|
||||||
|
layouts={layouts}
|
||||||
|
onCategory={onCategory}
|
||||||
|
onLayout={onLayout}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'w-full flex flex-wrap justify-center gap-28',
|
||||||
|
activeLayout === PROPERTIES_LAYOUTS.list && 'flex-col'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{renderedItems}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
scroll="content"
|
scroll="content"
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
|
import { lazy } from 'react';
|
||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
|
|
||||||
import authRoles from '../../../configs/authRoles';
|
import authRoles from '../../../configs/consts';
|
||||||
import History from './History';
|
|
||||||
import en from './i18n/en';
|
import en from './i18n/en';
|
||||||
|
|
||||||
i18next.addResourceBundle('en', 'historyPage', en);
|
i18next.addResourceBundle('en', 'historyPage', en);
|
||||||
|
|
||||||
|
const History = lazy(() => import('./History'));
|
||||||
|
|
||||||
const HistoryConfig = {
|
const HistoryConfig = {
|
||||||
settings: {
|
settings: {
|
||||||
layout: {
|
layout: {
|
||||||
@@ -22,28 +24,3 @@ const HistoryConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default HistoryConfig;
|
export default HistoryConfig;
|
||||||
|
|
||||||
/**
|
|
||||||
* Lazy load Example
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const Example = lazy(() => import('./Example'));
|
|
||||||
|
|
||||||
const ExampleConfig = {
|
|
||||||
settings: {
|
|
||||||
layout: {
|
|
||||||
config: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
routes: [
|
|
||||||
{
|
|
||||||
path: 'example',
|
|
||||||
element: <Example />,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ExampleConfig;
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { lazy } from 'react';
|
import { lazy } from 'react';
|
||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
|
|
||||||
import authRoles from '../../../configs/authRoles';
|
import authRoles from '../../../configs/consts';
|
||||||
import en from './i18n/en';
|
import en from './i18n/en';
|
||||||
|
|
||||||
i18next.addResourceBundle('en', 'profilePage', en);
|
i18next.addResourceBundle('en', 'profilePage', en);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export default class AuthService extends FuseUtils.EventEmitter {
|
|||||||
.then((userCredential) => firebaseAuth.updateProfile(userCredential.user, { displayName }))
|
.then((userCredential) => firebaseAuth.updateProfile(userCredential.user, { displayName }))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const userRef = firebaseDb.ref(this.#db, `users/${this.#auth.currentUser.uid}`);
|
const userRef = firebaseDb.ref(this.#db, `users/${this.#auth.currentUser.uid}`);
|
||||||
const value = { role: 'user', data: { displayName, email } };
|
const value = { role: 'user', data: { displayName, email }, favorites: [] };
|
||||||
|
|
||||||
return firebaseDb.set(userRef, value);
|
return firebaseDb.set(userRef, value);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const config = {
|
|||||||
title: 'Layout 1 - Dashboard',
|
title: 'Layout 1 - Dashboard',
|
||||||
defaults: {
|
defaults: {
|
||||||
mode: 'container',
|
mode: 'container',
|
||||||
containerWidth: 1570,
|
containerWidth: 1590,
|
||||||
navbar: {
|
navbar: {
|
||||||
display: true,
|
display: true,
|
||||||
folded: true,
|
folded: true,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { navbarCloseMobile, selectFuseNavbar } from 'app/store/fuse/navbarSlice'
|
|||||||
import { selectFuseCurrentLayoutConfig } from 'app/store/fuse/settingsSlice';
|
import { selectFuseCurrentLayoutConfig } from 'app/store/fuse/settingsSlice';
|
||||||
import NavbarLayout1Content from './NavbarLayout1Content';
|
import NavbarLayout1Content from './NavbarLayout1Content';
|
||||||
|
|
||||||
const navbarWidth = 280;
|
const navbarWidth = 330;
|
||||||
|
|
||||||
const StyledNavBar = styled('div')(({ theme, open, position }) => ({
|
const StyledNavBar = styled('div')(({ theme, open, position }) => ({
|
||||||
minWidth: navbarWidth,
|
minWidth: navbarWidth,
|
||||||
|
|||||||
@@ -186,6 +186,8 @@ module.exports = {
|
|||||||
primary: '#151B30',
|
primary: '#151B30',
|
||||||
secondary: '#6D6D6D',
|
secondary: '#6D6D6D',
|
||||||
disabled: '#D9D9D9',
|
disabled: '#D9D9D9',
|
||||||
|
highlight1: '#FFBC6E',
|
||||||
|
highlight2: '#DB00FF',
|
||||||
},
|
},
|
||||||
primary: {
|
primary: {
|
||||||
light: '#FFFFFF',
|
light: '#FFFFFF',
|
||||||
|
|||||||
Reference in New Issue
Block a user