-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: screen for empty observation and observation list (#84)
* Adds button in settings tab to create test data.
- Loading branch information
Showing
38 changed files
with
1,002 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import * as React from 'react' | ||
import type { Preset } from '@comapeo/schema' | ||
import { defineMessages, useIntl } from 'react-intl' | ||
|
||
const m = defineMessages({ | ||
observation: { | ||
// Keep id stable for translations | ||
id: 'screens.Observation.ObservationView.observation', | ||
defaultMessage: 'Observation', | ||
description: 'Default name of observation with no matching preset', | ||
}, | ||
}) | ||
|
||
// Format the translated preset name, with a fallback to "Observation" if no | ||
// preset is defined | ||
export const FormattedPresetName = ({ preset }: { preset?: Preset }) => { | ||
const { formatMessage: t } = useIntl() | ||
const name = preset | ||
? t({ id: `presets.${preset.docId}.name`, defaultMessage: preset.name }) | ||
: t(m.observation) | ||
|
||
return <React.Fragment>{name}</React.Fragment> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { styled } from '@mui/material/styles' | ||
import { defineMessages, useIntl } from 'react-intl' | ||
|
||
import { ALMOST_BLACK, BLUE_GREY, VERY_LIGHT_GREY } from '../../colors' | ||
import AddPersonIcon from '../../images/AddPerson.svg' | ||
import EmptyStateImage from '../../images/empty_state.png' | ||
import { Button } from '../Button' | ||
import { Text } from '../Text' | ||
|
||
const m = defineMessages({ | ||
inviteDevices: { | ||
id: 'emptyState.inviteDevices', | ||
defaultMessage: 'Invite Devices', | ||
}, | ||
noObservationsFound: { | ||
id: 'emptyState.noObservationsFound', | ||
defaultMessage: 'No Observations Found', | ||
}, | ||
}) | ||
|
||
const Container = styled('div')({ | ||
display: 'flex', | ||
flexDirection: 'column', | ||
padding: '25px 20px', | ||
}) | ||
|
||
const DividerLine = styled('div')({ | ||
width: '100%', | ||
height: 1, | ||
backgroundColor: VERY_LIGHT_GREY, | ||
}) | ||
|
||
const Circle = styled('div')({ | ||
width: 260, | ||
height: 260, | ||
borderRadius: '50%', | ||
backgroundColor: 'rgba(0, 102, 255, 0.1)', | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
}) | ||
|
||
const StyledImage = styled('img')({ | ||
width: 120, | ||
height: 120, | ||
}) | ||
|
||
const LowerContainer = styled('div')({ | ||
display: 'flex', | ||
flexDirection: 'column', | ||
alignItems: 'center', | ||
height: '75%', | ||
justifyContent: 'center', | ||
gap: 18, | ||
}) | ||
|
||
type EmptyStateProps = { | ||
onInviteDevices?: () => void | ||
} | ||
|
||
export function EmptyState({ onInviteDevices }: EmptyStateProps) { | ||
const { formatMessage } = useIntl() | ||
|
||
return ( | ||
<> | ||
<Container> | ||
<Button | ||
variant="outlined" | ||
style={{ | ||
borderColor: BLUE_GREY, | ||
color: ALMOST_BLACK, | ||
}} | ||
onClick={() => onInviteDevices?.()} | ||
startIcon={<AddPersonIcon color={ALMOST_BLACK} />} | ||
> | ||
{formatMessage(m.inviteDevices)} | ||
</Button> | ||
</Container> | ||
<DividerLine /> | ||
<LowerContainer> | ||
<Circle> | ||
<StyledImage src={EmptyStateImage} alt="Empty Observations List" /> | ||
</Circle> | ||
<Text kind="body">{formatMessage(m.noObservationsFound)}</Text> | ||
</LowerContainer> | ||
</> | ||
) | ||
} |
84 changes: 84 additions & 0 deletions
84
src/renderer/src/components/Observations/ObservationListItem.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import type { Observation } from '@comapeo/schema' | ||
import { styled } from '@mui/material/styles' | ||
import { FormattedDate, FormattedTime } from 'react-intl' | ||
|
||
import { VERY_LIGHT_GREY } from '../../colors' | ||
import { useActiveProjectIdStoreState } from '../../contexts/ActiveProjectIdProvider' | ||
import { useObservationWithPreset } from '../../hooks/useObservationWithPreset' | ||
import { FormattedPresetName } from '../FormattedData' | ||
import { PresetCircleIcon } from '../PresetCircleIcon' | ||
import { Text } from '../Text' | ||
|
||
type Props = { | ||
observation: Observation | ||
onClick?: () => void | ||
} | ||
|
||
const Container = styled('div')({ | ||
display: 'flex', | ||
flexDirection: 'row', | ||
alignItems: 'center', | ||
borderBottom: `1px solid ${VERY_LIGHT_GREY}`, | ||
padding: '10px 20px', | ||
cursor: 'pointer', | ||
width: '100%', | ||
'&:hover': { | ||
backgroundColor: '#f9f9f9', | ||
}, | ||
}) | ||
|
||
const TextContainer = styled('div')({ | ||
flex: 1, | ||
display: 'flex', | ||
flexDirection: 'column', | ||
}) | ||
|
||
const PhotoContainer = styled('img')({ | ||
width: 48, | ||
height: 48, | ||
borderRadius: 6, | ||
objectFit: 'cover', | ||
}) | ||
|
||
export function ObservationListItem({ observation, onClick }: Props) { | ||
const projectId = useActiveProjectIdStoreState((s) => s.activeProjectId) | ||
// TODO: Ideally, the fallback shouldn't be necessary | ||
const preset = useObservationWithPreset(observation, projectId ?? '') | ||
const createdAt = observation.createdAt | ||
? new Date(observation.createdAt) | ||
: new Date() | ||
|
||
const photoAttachment = observation.attachments.find( | ||
(att) => att.type === 'photo', | ||
) | ||
|
||
return ( | ||
<Container onClick={onClick}> | ||
<TextContainer> | ||
<Text bold> | ||
<FormattedPresetName preset={preset} /> | ||
</Text> | ||
<Text kind="caption"> | ||
<FormattedDate | ||
value={createdAt} | ||
month="short" | ||
day="2-digit" | ||
year="numeric" | ||
/> | ||
{', '} | ||
<FormattedTime value={createdAt} hour="numeric" minute="2-digit" /> | ||
</Text> | ||
</TextContainer> | ||
{photoAttachment ? ( | ||
<PhotoContainer src="/path/to/mock/photo.jpg" alt="Observation photo" /> | ||
) : ( | ||
<PresetCircleIcon | ||
projectId={projectId} | ||
iconId={preset?.iconRef?.docId} | ||
borderColor={preset?.color} | ||
size="medium" | ||
/> | ||
)} | ||
</Container> | ||
) | ||
} |
Oops, something went wrong.