RC-14: create dashboard page #8
@@ -8,7 +8,6 @@ function Welcome({ t }) {
|
|||||||
const onInputType = (event) => {
|
const onInputType = (event) => {
|
||||||
const { target } = event;
|
const { target } = event;
|
||||||
const value = target?.value ?? '';
|
const value = target?.value ?? '';
|
||||||
console.log(value);
|
|
||||||
setQuery(value);
|
setQuery(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -26,6 +25,7 @@ function Welcome({ t }) {
|
|||||||
{t('subtitle')}
|
{t('subtitle')}
|
||||||
</p>
|
</p>
|
||||||
<SearchInput
|
<SearchInput
|
||||||
|
className="max-w-[780px]"
|
||||||
mode="simple"
|
mode="simple"
|
||||||
placeholder={t('main_input_placeholder')}
|
placeholder={t('main_input_placeholder')}
|
||||||
btnText={t('main_input_btn')}
|
btnText={t('main_input_btn')}
|
||||||
|
|||||||
@@ -1,7 +1,43 @@
|
|||||||
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/Paper';
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { withTranslation } from 'react-i18next';
|
||||||
|
import SearchInput from '../../shared-components/SearchInput';
|
||||||
|
import DashboardCategory from '../shared-components/DashboardCategory';
|
||||||
|
|
||||||
|
const categoriesMock = [
|
||||||
|
{
|
||||||
|
title: 'All Properties',
|
||||||
|
value: 34,
|
||||||
|
valueColor: 'secondary-main',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'New',
|
||||||
|
value: 12,
|
||||||
|
valueColor: 'common-highlight2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'In Research',
|
||||||
|
value: 3,
|
||||||
|
valueColor: 'secondary-main',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Interested',
|
||||||
|
value: 25,
|
||||||
|
valueColor: 'common-highlight1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Purchased',
|
||||||
|
value: 8,
|
||||||
|
valueColor: 'accept-main',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Not Interested',
|
||||||
|
value: 11,
|
||||||
|
valueColor: 'error-main',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const Root = styled(FusePageSimple)(({ theme }) => ({
|
const Root = styled(FusePageSimple)(({ theme }) => ({
|
||||||
'& .FusePageSimple-header': {
|
'& .FusePageSimple-header': {
|
||||||
@@ -16,21 +52,39 @@ const Root = styled(FusePageSimple)(({ theme }) => ({
|
|||||||
'& .FusePageSimple-sidebarContent': {},
|
'& .FusePageSimple-sidebarContent': {},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function DashboardPage(props) {
|
function DashboardPage({ t }) {
|
||||||
const { t } = useTranslation('dashboardPage');
|
const [query, setQuery] = useState('');
|
||||||
|
|
||||||
|
const onInputType = (event) => {
|
||||||
|
const { target } = event;
|
||||||
|
const value = target?.value ?? '';
|
||||||
|
setQuery(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSearch = () => {
|
||||||
|
// query
|
||||||
|
};
|
||||||
|
|
||||||
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>
|
<div className="flex flex-wrap justify-center items-center gap-20 mb-52">
|
||||||
<br />
|
{categoriesMock.map(({ title, value, valueColor }) => (
|
||||||
<DemoContent />
|
<DashboardCategory title={title} value={value} valueColor={valueColor} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SearchInput
|
||||||
|
className="mb-28"
|
||||||
|
mode="manual"
|
||||||
|
btnText={t('search_input_btn')}
|
||||||
|
query={query}
|
||||||
|
onType={onInputType}
|
||||||
|
onSearch={onSearch}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Paper className="w-full h-640 mb-[30px] rounded-20 shadow-light" />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
scroll="content"
|
scroll="content"
|
||||||
@@ -38,4 +92,4 @@ function DashboardPage(props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DashboardPage;
|
export default withTranslation('dashboardPage')(DashboardPage);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
const locale = {};
|
const locale = {
|
||||||
|
search_input_btn: 'calculate',
|
||||||
|
};
|
||||||
|
|
||||||
export default locale;
|
export default locale;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import FusePageSimple from '@fuse/core/FusePageSimple';
|
import FusePageSimple from '@fuse/core/FusePageSimple';
|
||||||
import { Paper } from '@mui/material';
|
import Paper from '@mui/material/Paper';
|
||||||
import { styled } from '@mui/material/styles';
|
import { styled } from '@mui/material/styles';
|
||||||
import { PROPERTIES_LAYOUTS } from 'app/configs/consts';
|
import { PROPERTIES_LAYOUTS } from 'app/configs/consts';
|
||||||
import { selectUserFavorites, updateUserFavorites } from 'app/store/userSlice';
|
import { selectUserFavorites, updateUserFavorites } from 'app/store/userSlice';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import FusePageSimple from '@fuse/core/FusePageSimple';
|
import FusePageSimple from '@fuse/core/FusePageSimple';
|
||||||
import { Paper } from '@mui/material';
|
import Paper from '@mui/material/Paper';
|
||||||
import { styled } from '@mui/material/styles';
|
import { styled } from '@mui/material/styles';
|
||||||
import { PROPERTIES_LAYOUTS } from 'app/configs/consts';
|
import { PROPERTIES_LAYOUTS } from 'app/configs/consts';
|
||||||
import { selectUserHistory, updateUserFavorites, updateUserHistory } from 'app/store/userSlice';
|
import { selectUserHistory, updateUserFavorites, updateUserHistory } from 'app/store/userSlice';
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import Typography from '@mui/material/Typography';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { memo } from 'react';
|
||||||
|
|
||||||
|
function DashboardCategory({ className, title, value, valueColor }) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={clsx(
|
||||||
|
'flex flex-col items-center justify-center gap-24 max-w-224 w-full h-160 p-24 bg-white shadow-light rounded-20',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Typography variant="body1" className="text-lg text-common-layout font-medium">
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
className={clsx('text-5xl font-bold', valueColor && `text-${valueColor}`)}
|
||||||
|
>
|
||||||
|
{value}
|
||||||
|
</Typography>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(DashboardCategory);
|
||||||
@@ -1,7 +1,14 @@
|
|||||||
import { forwardRef, memo, useCallback } from 'react';
|
|
||||||
import TextField from '@mui/material/TextField';
|
|
||||||
import Button from '@mui/material/Button';
|
|
||||||
import _ from '@lodash';
|
import _ from '@lodash';
|
||||||
|
import Button from '@mui/material/Button';
|
||||||
|
// import Select from '@mui/material/Select';
|
||||||
|
import TextField from '@mui/material/TextField';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { forwardRef, memo, useCallback } from 'react';
|
||||||
|
|
||||||
|
const SEARCH_INPUT_MODES = {
|
||||||
|
simple: 'simple',
|
||||||
|
manual: 'manual',
|
||||||
|
};
|
||||||
|
|
||||||
const StyledTextField = forwardRef((props, ref) => (
|
const StyledTextField = forwardRef((props, ref) => (
|
||||||
<TextField
|
<TextField
|
||||||
@@ -19,28 +26,32 @@ const StyledTextField = forwardRef((props, ref) => (
|
|||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
function SearchInput({ mode, placeholder, btnText, query, onType, onSearch }) {
|
function SearchInput({ className, mode, placeholder, btnText, query, onType, onSearch }) {
|
||||||
const isSimpleMode = mode === 'simple';
|
const isSimpleMode = mode === SEARCH_INPUT_MODES.simple;
|
||||||
|
const isManualMode = mode === SEARCH_INPUT_MODES.manual;
|
||||||
|
const hasBtn = isSimpleMode || isManualMode;
|
||||||
|
|
||||||
const debouncedOnType = useCallback(_.debounce(onType, 250), [onType]);
|
const debouncedOnType = useCallback(_.debounce(onType, 250), [onType]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="flex items-center gap-20">
|
<form className={clsx('flex items-center gap-20', className)}>
|
||||||
<StyledTextField
|
<StyledTextField
|
||||||
type="text"
|
type="text"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
className="max-w-[620px] w-full bourder-0"
|
className="w-full bourder-0"
|
||||||
defaultValue={query}
|
defaultValue={query}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder ?? ''}
|
||||||
onChange={debouncedOnType}
|
onChange={debouncedOnType}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{isSimpleMode && (
|
{/* {isManualMode && <Select />} */}
|
||||||
|
|
||||||
|
{hasBtn && (
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
className="text-center text-base text-primary-light font-semibold tracking-widest uppercase rounded-2xl bg-secondary-light shadow hover:shadow-hover hover:shadow-secondary-light ease-in-out duration-300"
|
className="text-center text-base text-primary-light font-semibold tracking-widest uppercase rounded-2xl bg-secondary-light shadow hover:shadow-hover hover:shadow-secondary-light ease-in-out duration-300"
|
||||||
aria-label={btnText}
|
aria-label={btnText ?? ''}
|
||||||
type="button"
|
type="button"
|
||||||
size="large"
|
size="large"
|
||||||
onClick={onSearch}
|
onClick={onSearch}
|
||||||
|
|||||||
Reference in New Issue
Block a user