diff --git a/examples/demo/src/dashboard/CardIcon.js b/examples/demo/src/dashboard/CardIcon.tsx similarity index 71% rename from examples/demo/src/dashboard/CardIcon.js rename to examples/demo/src/dashboard/CardIcon.tsx index ce34fa42347..303544b3404 100644 --- a/examples/demo/src/dashboard/CardIcon.js +++ b/examples/demo/src/dashboard/CardIcon.tsx @@ -1,6 +1,12 @@ -import React from 'react'; +import React, { FC, ComponentType } from 'react'; import Card from '@material-ui/core/Card'; import { makeStyles } from '@material-ui/core/styles'; +import { SvgIconProps } from '@material-ui/core/SvgIcon'; + +interface Props { + bgColor: string; + Icon: ComponentType; +} const useStyles = makeStyles({ card: { @@ -18,7 +24,7 @@ const useStyles = makeStyles({ }, }); -const CardIcon = ({ Icon, bgColor }) => { +const CardIcon: FC = ({ Icon, bgColor }) => { const classes = useStyles(); return ( diff --git a/examples/demo/src/dashboard/Dashboard.js b/examples/demo/src/dashboard/Dashboard.tsx similarity index 72% rename from examples/demo/src/dashboard/Dashboard.js rename to examples/demo/src/dashboard/Dashboard.tsx index e51101849fe..1559ab9076a 100644 --- a/examples/demo/src/dashboard/Dashboard.js +++ b/examples/demo/src/dashboard/Dashboard.tsx @@ -1,6 +1,12 @@ -import React, { useState, useEffect, useCallback } from 'react'; +import React, { + useState, + useEffect, + useCallback, + FC, + CSSProperties, +} from 'react'; import { useVersion, useDataProvider } from 'react-admin'; -import { useMediaQuery } from '@material-ui/core'; +import { useMediaQuery, Theme } from '@material-ui/core'; import Welcome from './Welcome'; import MonthlyRevenue from './MonthlyRevenue'; @@ -9,6 +15,28 @@ import PendingOrders from './PendingOrders'; import PendingReviews from './PendingReviews'; import NewCustomers from './NewCustomers'; +import { Customer, Order, Review } from '../types'; + +interface OrderStats { + revenue: number; + nbNewOrders: number; + pendingOrders: Order[]; +} + +interface CustomerData { + [key: string]: Customer; +} + +interface State { + nbNewOrders?: number; + nbPendingReviews?: number; + pendingOrders?: Order[]; + pendingOrdersCustomers?: CustomerData; + pendingReviews?: Review[]; + pendingReviewsCustomers?: CustomerData; + revenue?: number; +} + const styles = { flex: { display: 'flex' }, flexColumn: { display: 'flex', flexDirection: 'column' }, @@ -17,12 +45,16 @@ const styles = { singleCol: { marginTop: '2em', marginBottom: '2em' }, }; -const Dashboard = () => { - const [state, setState] = useState({}); +const Dashboard: FC = () => { + const [state, setState] = useState({} as State); const version = useVersion(); const dataProvider = useDataProvider(); - const isXSmall = useMediaQuery(theme => theme.breakpoints.down('xs')); - const isSmall = useMediaQuery(theme => theme.breakpoints.down('sm')); + const isXSmall = useMediaQuery((theme: Theme) => + theme.breakpoints.down('xs') + ); + const isSmall = useMediaQuery((theme: Theme) => + theme.breakpoints.down('sm') + ); const fetchOrders = useCallback(async () => { const aMonthAgo = new Date(); @@ -33,9 +65,9 @@ const Dashboard = () => { pagination: { page: 1, perPage: 50 }, }); const aggregations = recentOrders - .filter(order => order.status !== 'cancelled') + .filter((order: Order) => order.status !== 'cancelled') .reduce( - (stats, order) => { + (stats: OrderStats, order: Order) => { if (order.status !== 'cancelled') { stats.revenue += order.total; stats.nbNewOrders++; @@ -63,14 +95,19 @@ const Dashboard = () => { pendingOrders: aggregations.pendingOrders, })); const { data: customers } = await dataProvider.getMany('customers', { - ids: aggregations.pendingOrders.map(order => order.customer_id), + ids: aggregations.pendingOrders.map( + (order: Order) => order.customer_id + ), }); setState(state => ({ ...state, - pendingOrdersCustomers: customers.reduce((prev, customer) => { - prev[customer.id] = customer; // eslint-disable-line no-param-reassign - return prev; - }, {}), + pendingOrdersCustomers: customers.reduce( + (prev: CustomerData, customer: Customer) => { + prev[customer.id] = customer; // eslint-disable-line no-param-reassign + return prev; + }, + {} + ), })); }, [dataProvider]); @@ -80,18 +117,21 @@ const Dashboard = () => { sort: { field: 'date', order: 'DESC' }, pagination: { page: 1, perPage: 100 }, }); - const nbPendingReviews = reviews.reduce(nb => ++nb, 0); + const nbPendingReviews = reviews.reduce((nb: number) => ++nb, 0); const pendingReviews = reviews.slice(0, Math.min(10, reviews.length)); setState(state => ({ ...state, pendingReviews, nbPendingReviews })); const { data: customers } = await dataProvider.getMany('customers', { - ids: pendingReviews.map(review => review.customer_id), + ids: pendingReviews.map((review: Review) => review.customer_id), }); setState(state => ({ ...state, - pendingReviewsCustomers: customers.reduce((prev, customer) => { - prev[customer.id] = customer; // eslint-disable-line no-param-reassign - return prev; - }, {}), + pendingReviewsCustomers: customers.reduce( + (prev: CustomerData, customer: Customer) => { + prev[customer.id] = customer; // eslint-disable-line no-param-reassign + return prev; + }, + {} + ), })); }, [dataProvider]); @@ -111,7 +151,7 @@ const Dashboard = () => { } = state; return isXSmall ? (
-
+
@@ -128,7 +168,7 @@ const Dashboard = () => {
) : isSmall ? ( -
+
diff --git a/examples/demo/src/dashboard/MonthlyRevenue.js b/examples/demo/src/dashboard/MonthlyRevenue.tsx similarity index 88% rename from examples/demo/src/dashboard/MonthlyRevenue.js rename to examples/demo/src/dashboard/MonthlyRevenue.tsx index 608e9bd9946..4c39a8829f0 100644 --- a/examples/demo/src/dashboard/MonthlyRevenue.js +++ b/examples/demo/src/dashboard/MonthlyRevenue.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { FC } from 'react'; import Card from '@material-ui/core/Card'; import DollarIcon from '@material-ui/icons/AttachMoney'; import { makeStyles } from '@material-ui/core/styles'; @@ -7,6 +7,10 @@ import { useTranslate } from 'react-admin'; import CardIcon from './CardIcon'; +interface Props { + value: number; +} + const useStyles = makeStyles({ main: { flex: '1', @@ -19,9 +23,10 @@ const useStyles = makeStyles({ padding: 16, minHeight: 52, }, + title: {}, }); -const MonthlyRevenue = ({ value }) => { +const MonthlyRevenue: FC = ({ value }) => { const translate = useTranslate(); const classes = useStyles(); return ( diff --git a/examples/demo/src/dashboard/NbNewOrders.js b/examples/demo/src/dashboard/NbNewOrders.tsx similarity index 89% rename from examples/demo/src/dashboard/NbNewOrders.js rename to examples/demo/src/dashboard/NbNewOrders.tsx index dc454ba1f1d..c110c2d54ac 100644 --- a/examples/demo/src/dashboard/NbNewOrders.js +++ b/examples/demo/src/dashboard/NbNewOrders.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { FC } from 'react'; import Card from '@material-ui/core/Card'; import ShoppingCartIcon from '@material-ui/icons/ShoppingCart'; import { makeStyles } from '@material-ui/core/styles'; @@ -7,6 +7,10 @@ import { useTranslate } from 'react-admin'; import CardIcon from './CardIcon'; +interface Props { + value: number; +} + const useStyles = makeStyles({ main: { flex: '1', @@ -19,9 +23,10 @@ const useStyles = makeStyles({ padding: 16, minHeight: 52, }, + title: {}, }); -const NbNewOrders = ({ value }) => { +const NbNewOrders: FC = ({ value }) => { const translate = useTranslate(); const classes = useStyles(); return ( diff --git a/examples/demo/src/dashboard/NewCustomers.js b/examples/demo/src/dashboard/NewCustomers.tsx similarity index 95% rename from examples/demo/src/dashboard/NewCustomers.js rename to examples/demo/src/dashboard/NewCustomers.tsx index 19ced20710a..d7270016ac1 100644 --- a/examples/demo/src/dashboard/NewCustomers.js +++ b/examples/demo/src/dashboard/NewCustomers.tsx @@ -13,6 +13,7 @@ import { Link } from 'react-router-dom'; import { useTranslate, useQueryWithStore } from 'react-admin'; import CardIcon from './CardIcon'; +import { Customer } from '../types'; const useStyles = makeStyles({ main: { @@ -62,7 +63,7 @@ const NewCustomers = () => { if (!loaded) return null; - const nb = visitors ? visitors.reduce(nb => ++nb, 0) : 0; + const nb = visitors ? visitors.reduce((nb: number) => ++nb, 0) : 0; return (
@@ -80,7 +81,7 @@ const NewCustomers = () => { {visitors - ? visitors.map(record => ( + ? visitors.map((record: Customer) => ( ({ root: { @@ -21,7 +27,7 @@ const useStyles = makeStyles(theme => ({ }, })); -const PendingOrders = ({ orders = [], customers = {} }) => { +const PendingOrders: FC = ({ orders = [], customers = {} }) => { const classes = useStyles(); const translate = useTranslate(); return ( diff --git a/examples/demo/src/dashboard/PendingReviews.js b/examples/demo/src/dashboard/PendingReviews.tsx similarity index 84% rename from examples/demo/src/dashboard/PendingReviews.js rename to examples/demo/src/dashboard/PendingReviews.tsx index ef86a2a5d66..4def1ec571d 100644 --- a/examples/demo/src/dashboard/PendingReviews.js +++ b/examples/demo/src/dashboard/PendingReviews.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { FC } from 'react'; import Card from '@material-ui/core/Card'; import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; @@ -15,6 +15,13 @@ import { useTranslate } from 'react-admin'; import CardIcon from './CardIcon'; import StarRatingField from '../reviews/StarRatingField'; +import { Customer, Review } from '../types'; + +interface Props { + reviews: Review[]; + customers: { [key: string]: Customer }; + nb: number; +} const useStyles = makeStyles(theme => ({ main: { @@ -36,7 +43,7 @@ const useStyles = makeStyles(theme => ({ minHeight: 48, }, avatar: { - background: theme.palette.background.avatar, + background: theme.palette.background.paper, }, listItemText: { overflowY: 'hidden', @@ -52,7 +59,7 @@ const location = { query: { filter: JSON.stringify({ status: 'pending' }) }, }; -const PendingReviews = ({ reviews = [], customers = {}, nb }) => { +const PendingReviews: FC = ({ reviews = [], customers = {}, nb }) => { const classes = useStyles(); const translate = useTranslate(); return ( @@ -73,7 +80,7 @@ const PendingReviews = ({ reviews = [], customers = {}, nb }) => { - {reviews.map(record => ( + {reviews.map((record: Review) => ( { } + primary={ + + } secondary={record.comment} className={classes.listItemText} style={{ paddingRight: 0 }} diff --git a/examples/demo/src/dashboard/Welcome.js b/examples/demo/src/dashboard/Welcome.tsx similarity index 94% rename from examples/demo/src/dashboard/Welcome.js rename to examples/demo/src/dashboard/Welcome.tsx index 4b44f623a8d..b34c4f91033 100644 --- a/examples/demo/src/dashboard/Welcome.js +++ b/examples/demo/src/dashboard/Welcome.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { FC } from 'react'; import Card from '@material-ui/core/Card'; import CardActions from '@material-ui/core/CardActions'; import CardContent from '@material-ui/core/CardContent'; @@ -17,11 +17,11 @@ const useStyles = makeStyles({ }); const mediaUrl = `https://marmelab.com/posters/beard-${parseInt( - Math.random() * 10, + (Math.random() * 10).toString(), 10 ) + 1}.jpeg`; -const Welcome = () => { +const Welcome: FC = () => { const translate = useTranslate(); const classes = useStyles(); return ( diff --git a/examples/demo/src/dashboard/index.js b/examples/demo/src/dashboard/index.ts similarity index 100% rename from examples/demo/src/dashboard/index.js rename to examples/demo/src/dashboard/index.ts diff --git a/examples/demo/src/types.ts b/examples/demo/src/types.ts index b28aeaf4fe1..ffdd27b048f 100644 --- a/examples/demo/src/types.ts +++ b/examples/demo/src/types.ts @@ -58,3 +58,7 @@ export interface FieldProps { record?: T; source?: string; } + +export interface Review extends Record { + customer_id: string; +}