Skip to content

Commit

Permalink
Merge pull request #9854 from marmelab/crm-changes
Browse files Browse the repository at this point in the history
[Demo] Improve CRM demo
  • Loading branch information
adguernier committed May 17, 2024
2 parents f1ab8e3 + 9166b4b commit 78c1090
Show file tree
Hide file tree
Showing 18 changed files with 415 additions and 159 deletions.
8 changes: 7 additions & 1 deletion examples/crm/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ const App = () => (
<Resource name="contactNotes" />
<Resource name="dealNotes" />
<Resource name="tasks" list={ListGuesser} />
<Resource name="sales" list={ListGuesser} />
<Resource
name="sales"
list={ListGuesser}
recordRepresentation={(record: any) =>
`${record.first_name} ${record.last_name}`
}
/>
<Resource name="tags" list={ListGuesser} />
</Admin>
);
Expand Down
18 changes: 14 additions & 4 deletions examples/crm/src/companies/CompanyAside.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,19 @@ export const CompanyAside = ({ link = 'edit' }: CompanyAsideProps) => {

<Box mt={2}>
<Typography variant="body2">
Website: <Link href={record.website}>{record.website}</Link>
<br />
LinkedIn: <Link href={record.linkedIn}>LinkedIn</Link>
{record.website && (
<>
Website:{' '}
<Link href={record.website}>{record.website}</Link>
</>
)}
{record.linkedIn && (
<>
<br />
LinkedIn:{' '}
<Link href={record.linkedIn}>LinkedIn</Link>
</>
)}
</Typography>
</Box>

Expand All @@ -47,7 +57,7 @@ export const CompanyAside = ({ link = 'edit' }: CompanyAsideProps) => {
color="textSecondary"
component="span"
>
Main
Main Address
</Typography>
</Box>

Expand Down
106 changes: 65 additions & 41 deletions examples/crm/src/companies/CompanyShow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
useRecordContext,
useListContext,
RecordContextProvider,
SortButton,
} from 'react-admin';
import {
Box,
Expand All @@ -24,6 +25,7 @@ import {
Tabs,
Tab,
Divider,
Stack,
} from '@mui/material';
import PersonAddIcon from '@mui/icons-material/PersonAdd';
import { Link as RouterLink } from 'react-router-dom';
Expand Down Expand Up @@ -63,7 +65,8 @@ const CompanyShowContent = () => {
{record.name}
</Typography>
<Typography variant="body2">
<TextField source="sector" />,{' '}
<TextField source="sector" />
{record.size && ', '}
<SelectField
source="size"
choices={sizes}
Expand Down Expand Up @@ -103,6 +106,21 @@ const CompanyShowContent = () => {
target="company_id"
sort={{ field: 'last_name', order: 'ASC' }}
>
<Stack
direction="row"
justifyContent="flex-end"
spacing={2}
mt={1}
>
<SortButton
fields={[
'last_name',
'first_name',
'last_seen',
]}
/>
<CreateRelatedContactButton />
</Stack>
<ContactsIterator />
</ReferenceManyField>
</TabPanel>
Expand Down Expand Up @@ -151,45 +169,52 @@ const ContactsIterator = () => {

const now = Date.now();
return (
<Box>
<List dense>
{contacts.map(contact => (
<RecordContextProvider key={contact.id} value={contact}>
<ListItem
button
component={RouterLink}
to={`/contacts/${contact.id}/show`}
>
<ListItemAvatar>
<Avatar />
</ListItemAvatar>
<ListItemText
primary={`${contact.first_name} ${contact.last_name}`}
secondary={
<>
{contact.title} <TagsList />
</>
}
/>
<ListItemSecondaryAction>
<Typography
variant="body2"
color="textSecondary"
component="span"
>
last activity{' '}
{formatDistance(contact.last_seen, now)} ago{' '}
<Status status={contact.status} />
</Typography>
</ListItemSecondaryAction>
</ListItem>
</RecordContextProvider>
))}
</List>
<Box textAlign="center" mt={1}>
<CreateRelatedContactButton />
</Box>
</Box>
<List dense sx={{ pt: 0 }}>
{contacts.map(contact => (
<RecordContextProvider key={contact.id} value={contact}>
<ListItem
button
component={RouterLink}
to={`/contacts/${contact.id}/show`}
>
<ListItemAvatar>
<Avatar />
</ListItemAvatar>
<ListItemText
primary={`${contact.first_name} ${contact.last_name}`}
secondary={
<>
{contact.title}
{contact.nb_notes
? ` - ${contact.nb_notes} note${
contact.nb_notes > 1 ? 's' : ''
}`
: ''}
{contact.nb_tasks
? ` - ${contact.nb_tasks} task${
contact.nb_tasks > 1 ? 's' : ''
}`
: ''}
&nbsp; &nbsp;
<TagsList />
</>
}
/>
<ListItemSecondaryAction>
<Typography
variant="body2"
color="textSecondary"
component="span"
>
last activity{' '}
{formatDistance(contact.last_seen, now)} ago{' '}
<Status status={contact.status} />
</Typography>
</ListItemSecondaryAction>
</ListItem>
</RecordContextProvider>
))}
</List>
);
};

Expand All @@ -201,7 +226,6 @@ const CreateRelatedContactButton = () => {
to="/contacts/create"
state={company ? { record: { company_id: company.id } } : undefined}
color="primary"
variant="contained"
size="small"
startIcon={<PersonAddIcon />}
>
Expand Down
2 changes: 1 addition & 1 deletion examples/crm/src/companies/LogoField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const LogoField = ({
size?: 'small' | 'medium';
}) => {
const record = useRecordContext<Company>();
if (!record) return null;
if (!record || !record.logo) return null;
return (
<Box
component="img"
Expand Down
56 changes: 31 additions & 25 deletions examples/crm/src/contacts/ContactAside.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
EditButton,
ShowButton,
ReferenceField,
SelectField,
FunctionField,
useRecordContext,
} from 'react-admin';
Expand All @@ -16,9 +17,11 @@ import { AddTask } from '../tasks/AddTask';
import { TasksIterator } from '../tasks/TasksIterator';

import { Contact, Sale } from '../types';
import { genders } from './constants';

export const ContactAside = ({ link = 'edit' }: { link?: 'edit' | 'show' }) => {
const record = useRecordContext<Contact>();
if (!record) return null;
return (
<Box ml={4} width={250} minWidth={250}>
<Box textAlign="center" mb={2}>
Expand All @@ -30,32 +33,35 @@ export const ContactAside = ({ link = 'edit' }: { link?: 'edit' | 'show' }) => {
</Box>
<Typography variant="subtitle2">Personal info</Typography>
<Divider />
<EmailField
sx={{ mt: 2, mb: 1, display: 'block' }}
source="email"
/>
<TextField source="phone_number1" />{' '}
<Typography variant="body2" color="textSecondary" component="span">
Work
<EmailField sx={{ mt: 2, display: 'block' }} source="email" />
{record.phone_number1 && (
<Box>
<TextField source="phone_number1" />{' '}
<Typography
variant="body2"
color="textSecondary"
component="span"
>
Work
</Typography>
</Box>
)}
{record.phone_number2 && (
<Box>
<TextField source="phone_number2" />{' '}
<Typography
variant="body2"
color="textSecondary"
component="span"
>
Home
</Typography>
</Box>
)}
<SelectField source="gender" choices={genders} />
<Typography variant="subtitle2" mt={2}>
Background
</Typography>
<Box mb={1}>
<TextField source="phone_number2" />{' '}
<Typography
variant="body2"
color="textSecondary"
component="span"
>
Home
</Typography>
</Box>
<Typography variant="body2" mb={3}>
{record
? record.gender === 'male'
? 'He/Him'
: 'She/Her'
: ''}
</Typography>
<Typography variant="subtitle2">Background</Typography>
<Divider />
<Typography variant="body2" mt={2}>
{record && record.background}
Expand Down
60 changes: 32 additions & 28 deletions examples/crm/src/contacts/ContactCreate.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
import * as React from 'react';
import { CreateBase, Form, Toolbar } from 'react-admin';
import { CreateBase, Form, Toolbar, useGetIdentity } from 'react-admin';
import { Card, CardContent, Box, Avatar } from '@mui/material';

import { ContactInputs } from './ContactInputs';
import { Contact } from '../types';

export const ContactCreate = () => (
<CreateBase
redirect="show"
transform={(data: Contact) => ({
...data,
last_seen: new Date(),
tags: [],
})}
>
<Box mt={2} display="flex">
<Box flex="1">
<Form>
<Card>
<CardContent>
<Box>
<Box display="flex">
<Box mr={2}>
<Avatar />
export const ContactCreate = () => {
const { identity } = useGetIdentity();
return (
<CreateBase
redirect="show"
transform={(data: Contact) => ({
...data,
first_seen: new Date().toISOString(),
last_seen: new Date().toISOString(),
tags: [],
})}
>
<Box mt={2} display="flex">
<Box flex="1">
<Form defaultValues={{ sales_id: identity?.id }}>
<Card>
<CardContent>
<Box>
<Box display="flex">
<Box mr={2}>
<Avatar />
</Box>
<ContactInputs />
</Box>
<ContactInputs />
</Box>
</Box>
</CardContent>
<Toolbar />
</Card>
</Form>
</CardContent>
<Toolbar />
</Card>
</Form>
</Box>
</Box>
</Box>
</CreateBase>
);
</CreateBase>
);
};

0 comments on commit 78c1090

Please sign in to comment.