Skip to content

Commit fee5d0e

Browse files
authored
Merge pull request #5472 from marmelab/demo-visitor-action-timeline
[Demo] use stepper for customer actions
2 parents 6904d77 + 1d00dfe commit fee5d0e

File tree

1 file changed

+139
-140
lines changed

1 file changed

+139
-140
lines changed

examples/demo/src/visitors/Aside.tsx

+139-140
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,29 @@ import {
77
DateField,
88
useTranslate,
99
useGetList,
10-
linkToRecord,
1110
Record,
1211
RecordMap,
1312
Identifier,
13+
ReferenceField,
14+
useLocale,
1415
} from 'react-admin';
1516
import {
16-
Tooltip,
1717
Typography,
1818
Card,
1919
CardContent,
20-
CardHeader,
21-
Avatar,
22-
IconButton,
2320
Box,
21+
Link,
22+
Stepper,
23+
Step,
24+
StepLabel,
25+
StepContent,
2426
} from '@material-ui/core';
25-
import { Link } from 'react-router-dom';
27+
import { Link as RouterLink } from 'react-router-dom';
2628
import AccessTimeIcon from '@material-ui/icons/AccessTime';
27-
import ContentCreate from '@material-ui/icons/Create';
2829
import { makeStyles } from '@material-ui/core/styles';
2930

3031
import order from '../orders';
3132
import review from '../reviews';
32-
import ProductReferenceField from '../products/ProductReferenceField';
3333
import StarRatingField from '../reviews/StarRatingField';
3434
import { Order as OrderRecord, Review as ReviewRecord } from '../types';
3535

@@ -65,8 +65,19 @@ interface EventListProps {
6565
record?: Record;
6666
basePath?: string;
6767
}
68+
69+
const useEventStyles = makeStyles({
70+
stepper: {
71+
background: 'none',
72+
border: 'none',
73+
marginLeft: '0.3em',
74+
},
75+
});
76+
6877
const EventList: FC<EventListProps> = ({ record, basePath }) => {
6978
const translate = useTranslate();
79+
const classes = useEventStyles();
80+
const locale = useLocale();
7081
const { data: orders, ids: orderIds } = useGetList<OrderRecord>(
7182
'commands',
7283
{ page: 1, perPage: 100 },
@@ -180,22 +191,56 @@ const EventList: FC<EventListProps> = ({ record, basePath }) => {
180191
</CardContent>
181192
</Card>
182193
</Box>
183-
184-
{events.map(event =>
185-
event.type === 'order' ? (
186-
<Order
187-
record={event.data as OrderRecord}
188-
key={`event_${event.data.id}`}
189-
basePath={basePath}
190-
/>
191-
) : (
192-
<Review
193-
record={event.data as ReviewRecord}
194-
key={`review_${event.data.id}`}
195-
basePath={basePath}
196-
/>
197-
)
198-
)}
194+
<Stepper orientation="vertical" classes={{ root: classes.stepper }}>
195+
{events.map(event => (
196+
<Step
197+
key={`${event.type}-${event.data.id}`}
198+
expanded
199+
active
200+
completed
201+
>
202+
<StepLabel
203+
StepIconComponent={() => {
204+
const Component =
205+
event.type === 'order'
206+
? order.icon
207+
: review.icon;
208+
return (
209+
<Component
210+
fontSize="small"
211+
color="disabled"
212+
style={{ paddingLeft: 3 }}
213+
/>
214+
);
215+
}}
216+
>
217+
{new Date(event.date).toLocaleString(locale, {
218+
weekday: 'long',
219+
year: 'numeric',
220+
month: 'short',
221+
day: 'numeric',
222+
hour: 'numeric',
223+
minute: 'numeric',
224+
})}
225+
</StepLabel>
226+
<StepContent>
227+
{event.type === 'order' ? (
228+
<Order
229+
record={event.data as OrderRecord}
230+
key={`event_${event.data.id}`}
231+
basePath={basePath}
232+
/>
233+
) : (
234+
<Review
235+
record={event.data as ReviewRecord}
236+
key={`review_${event.data.id}`}
237+
basePath={basePath}
238+
/>
239+
)}
240+
</StepContent>
241+
</Step>
242+
))}
243+
</Stepper>
199244
</>
200245
);
201246
};
@@ -230,80 +275,51 @@ const mixOrdersAndReviews = (
230275
: [];
231276
const events = eventsFromOrders.concat(eventsFromReviews);
232277
events.sort(
233-
(e1, e2) => new Date(e1.date).getTime() - new Date(e2.date).getTime()
278+
(e1, e2) => new Date(e2.date).getTime() - new Date(e1.date).getTime()
234279
);
235280
return events;
236281
};
237282

238-
const useEventStyles = makeStyles({
239-
card: {
240-
margin: '0 0 1em 1em',
241-
},
242-
cardHeader: {
243-
alignItems: 'flex-start',
244-
},
245-
clamp: {
246-
display: '-webkit-box',
247-
'-webkit-line-clamp': 3,
248-
'-webkit-box-orient': 'vertical',
249-
overflow: 'hidden',
250-
},
251-
});
252-
253283
interface OrderProps {
254284
record?: OrderRecord;
255285
basePath?: string;
256286
}
257287

258288
const Order: FC<OrderProps> = ({ record, basePath }) => {
259289
const translate = useTranslate();
260-
const classes = useEventStyles();
261290
return record ? (
262-
<Card className={classes.card}>
263-
<CardHeader
264-
className={classes.cardHeader}
265-
avatar={
266-
<Avatar
267-
aria-label={translate('resources.commands.name', {
268-
smart_count: 1,
269-
})}
270-
>
271-
<order.icon />
272-
</Avatar>
273-
}
274-
action={<EditButton record={record} basePath="/commands" />}
275-
title={`${translate('resources.commands.name', {
276-
smart_count: 1,
277-
})} #${record.reference}`}
278-
subheader={
279-
<>
280-
<Typography variant="body2">{record.date}</Typography>
281-
<Typography variant="body2" color="textSecondary">
282-
{translate('resources.commands.nb_items', {
283-
smart_count: record.basket.length,
284-
_: '1 item |||| %{smart_count} items',
285-
})}
286-
&nbsp;-&nbsp;
287-
<NumberField
288-
source="total"
289-
options={{
290-
style: 'currency',
291-
currency: 'USD',
292-
}}
293-
record={record}
294-
basePath={basePath}
295-
/>
296-
&nbsp;-&nbsp;
297-
<TextField
298-
source="status"
299-
record={record}
300-
basePath={basePath}
301-
/>
302-
</Typography>
303-
</>
304-
}
305-
/>
306-
</Card>
291+
<>
292+
<Typography variant="body2" gutterBottom>
293+
<Link to={`/commands/${record.id}`} component={RouterLink}>
294+
{translate('resources.commands.name', {
295+
smart_count: 1,
296+
})}{' '}
297+
#{record.reference}
298+
</Link>
299+
</Typography>
300+
<Typography variant="body2" color="textSecondary">
301+
{translate('resources.commands.nb_items', {
302+
smart_count: record.basket.length,
303+
_: '1 item |||| %{smart_count} items',
304+
})}
305+
&nbsp;-&nbsp;
306+
<NumberField
307+
source="total"
308+
options={{
309+
style: 'currency',
310+
currency: 'USD',
311+
}}
312+
record={record}
313+
basePath={basePath}
314+
/>
315+
&nbsp;-&nbsp;
316+
<TextField
317+
source="status"
318+
record={record}
319+
basePath={basePath}
320+
/>
321+
</Typography>
322+
</>
307323
) : null;
308324
};
309325

@@ -312,65 +328,48 @@ interface ReviewProps {
312328
basePath?: string;
313329
}
314330

331+
const useReviewStyles = makeStyles({
332+
clamp: {
333+
display: '-webkit-box',
334+
'-webkit-line-clamp': 3,
335+
'-webkit-box-orient': 'vertical',
336+
overflow: 'hidden',
337+
},
338+
});
339+
315340
const Review: FC<ReviewProps> = ({ record, basePath }) => {
341+
const classes = useReviewStyles();
316342
const translate = useTranslate();
317-
const classes = useEventStyles();
318343
return record ? (
319-
<Card className={classes.card}>
320-
<CardHeader
321-
className={classes.cardHeader}
322-
avatar={
323-
<Avatar
324-
aria-label={translate('resources.reviews.name', {
325-
smart_count: 1,
326-
})}
344+
<>
345+
<Typography variant="body2" gutterBottom>
346+
<Link to={`/reviews/${record.id}`} component={RouterLink}>
347+
{translate('resources.reviews.relative_to_poster')} "
348+
<ReferenceField
349+
source="product_id"
350+
reference="products"
351+
resource="reviews"
352+
record={record}
353+
basePath={basePath}
354+
link={false}
327355
>
328-
<review.icon />
329-
</Avatar>
330-
}
331-
action={<EditButton record={record} basePath="/reviews" />}
332-
title={
333-
<span>
334-
{translate('resources.reviews.relative_to_poster')}{' '}
335-
<ProductReferenceField
336-
resource="reviews"
337-
record={record}
338-
basePath={basePath}
339-
/>
340-
</span>
341-
}
342-
subheader={
343-
<>
344-
<Typography variant="body2">{record.date}</Typography>
345-
<StarRatingField record={record} />
346-
<Typography variant="inherit" className={classes.clamp}>
347-
{record.comment}
348-
</Typography>
349-
</>
350-
}
351-
/>
352-
</Card>
353-
) : null;
354-
};
355-
356-
interface EditButtonProps {
357-
record?: Record;
358-
basePath?: string;
359-
}
360-
361-
const EditButton: FC<EditButtonProps> = ({ record, basePath }) => {
362-
const translate = useTranslate();
363-
return (
364-
<Tooltip title={translate('ra.action.edit')}>
365-
<IconButton
366-
aria-label={translate('ra.action.edit')}
367-
component={Link}
368-
to={linkToRecord(basePath, record && record.id)}
356+
<TextField source="reference" component="span" />
357+
</ReferenceField>
358+
"
359+
</Link>
360+
</Typography>
361+
<Typography variant="body2" color="textSecondary" gutterBottom>
362+
<StarRatingField record={record} />
363+
</Typography>
364+
<Typography
365+
variant="body2"
366+
color="textSecondary"
367+
className={classes.clamp}
369368
>
370-
<ContentCreate />
371-
</IconButton>
372-
</Tooltip>
373-
);
369+
{record.comment}
370+
</Typography>
371+
</>
372+
) : null;
374373
};
375374

376375
export default Aside;

0 commit comments

Comments
 (0)