fix: mobile styles + viewport
This commit is contained in:
parent
e0843fc89a
commit
cf3b79d4aa
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Box, MediaQuery } from '@mantine/core';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
|
@ -33,8 +34,8 @@ const TimeElapsed = ({ startTime, endTime }: Props) => {
|
||||||
.padStart(2, '0')}`;
|
.padStart(2, '0')}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Box
|
||||||
style={{
|
sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
|
@ -50,31 +51,38 @@ const TimeElapsed = ({ startTime, endTime }: Props) => {
|
||||||
>
|
>
|
||||||
<code>{hoursString}</code>
|
<code>{hoursString}</code>
|
||||||
</pre>
|
</pre>
|
||||||
<p
|
<MediaQuery
|
||||||
style={{
|
smallerThan="sm"
|
||||||
fontSize: '0.75rem',
|
styles={{
|
||||||
margin: 0
|
display: 'none'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>
|
<p
|
||||||
{Intl.DateTimeFormat('it-IT', {
|
style={{
|
||||||
hour: '2-digit',
|
fontSize: '0.75rem',
|
||||||
minute: '2-digit',
|
margin: 0
|
||||||
hour12: false
|
}}
|
||||||
}).format(new Date(startTime))}
|
>
|
||||||
</span>
|
<span>
|
||||||
<span dangerouslySetInnerHTML={{ __html: ' — ' }} />
|
{Intl.DateTimeFormat('it-IT', {
|
||||||
<span>
|
hour: '2-digit',
|
||||||
{endTime
|
minute: '2-digit',
|
||||||
? Intl.DateTimeFormat('it-IT', {
|
hour12: false
|
||||||
hour: '2-digit',
|
}).format(new Date(startTime))}
|
||||||
minute: '2-digit',
|
</span>
|
||||||
hour12: false
|
<span dangerouslySetInnerHTML={{ __html: ' — ' }} />
|
||||||
}).format(new Date(endTime))
|
<span>
|
||||||
: 'now'}
|
{endTime
|
||||||
</span>
|
? Intl.DateTimeFormat('it-IT', {
|
||||||
</p>
|
hour: '2-digit',
|
||||||
</div>
|
minute: '2-digit',
|
||||||
|
hour12: false
|
||||||
|
}).format(new Date(endTime))
|
||||||
|
: 'now'}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</MediaQuery>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
15
app/root.tsx
15
app/root.tsx
|
|
@ -126,6 +126,17 @@ function Document({
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charSet="utf-8" />
|
<meta charSet="utf-8" />
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
|
||||||
|
/>
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta
|
||||||
|
name="apple-mobile-web-app-status-bar-style"
|
||||||
|
content="default"
|
||||||
|
/>
|
||||||
|
<meta name="format-detection" content="telephone=no" />
|
||||||
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
{title ? <title>{title}</title> : null}
|
{title ? <title>{title}</title> : null}
|
||||||
<StylesPlaceholder />
|
<StylesPlaceholder />
|
||||||
<Meta />
|
<Meta />
|
||||||
|
|
@ -355,7 +366,7 @@ function Layout({ children }: React.PropsWithChildren<{}>) {
|
||||||
</UnstyledButton>
|
</UnstyledButton>
|
||||||
<UnstyledButton
|
<UnstyledButton
|
||||||
component={Link}
|
component={Link}
|
||||||
to="/"
|
to="/importexport"
|
||||||
sx={(theme) => ({
|
sx={(theme) => ({
|
||||||
display: 'block',
|
display: 'block',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|
@ -379,7 +390,7 @@ function Layout({ children }: React.PropsWithChildren<{}>) {
|
||||||
<Upload size={16} />
|
<Upload size={16} />
|
||||||
</ThemeIcon>
|
</ThemeIcon>
|
||||||
|
|
||||||
<Text size="sm">Import</Text>
|
<Text size="sm">Import/Export</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</UnstyledButton>
|
</UnstyledButton>
|
||||||
<UnstyledButton
|
<UnstyledButton
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ import {
|
||||||
Progress,
|
Progress,
|
||||||
Badge,
|
Badge,
|
||||||
ThemeIcon,
|
ThemeIcon,
|
||||||
Alert
|
Alert,
|
||||||
|
Box
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { json, LoaderArgs, MetaFunction, redirect } from '@remix-run/node';
|
import { json, LoaderArgs, MetaFunction, redirect } from '@remix-run/node';
|
||||||
import {
|
import {
|
||||||
|
|
@ -138,7 +139,8 @@ export default function TimeEntriesPage() {
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'flex-end',
|
alignItems: 'flex-end',
|
||||||
justifyContent: 'space-between'
|
justifyContent: 'space-between',
|
||||||
|
margin: '0.5rem 0'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<NativeSelect
|
<NativeSelect
|
||||||
|
|
@ -248,123 +250,171 @@ export default function TimeEntriesPage() {
|
||||||
radius="md"
|
radius="md"
|
||||||
mb="sm"
|
mb="sm"
|
||||||
display="flex"
|
display="flex"
|
||||||
style={{
|
sx={() => ({
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'column'
|
justifyContent: 'space-between',
|
||||||
}}
|
flexDirection: 'row'
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
<div
|
<Box
|
||||||
style={{
|
sx={() => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'flex-start',
|
||||||
|
flexDirection: 'column',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
width: '100%'
|
flexGrow: 1,
|
||||||
}}
|
width: '100%',
|
||||||
|
|
||||||
|
'@media (min-width: 601px)': {
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row'
|
||||||
|
}
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
<span
|
<Box
|
||||||
style={{
|
component="span"
|
||||||
marginRight: 'auto'
|
sx={{
|
||||||
|
display: 'inline-block',
|
||||||
|
marginRight: 'auto',
|
||||||
|
|
||||||
|
'@media (max-width: 600px)': {
|
||||||
|
marginBottom: '0.33rem'
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{timeEntry.description}
|
{timeEntry.description}
|
||||||
</span>
|
</Box>
|
||||||
{timeEntry.projectId && timeEntry.project && (
|
{timeEntry.projectId && timeEntry.project && (
|
||||||
<Badge color={timeEntry.project.color}>
|
<Badge color={timeEntry.project.color}>
|
||||||
{timeEntry.project.name}
|
{timeEntry.project.name}
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'column',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
flexShrink: 1,
|
||||||
|
flexGrow: 0,
|
||||||
|
|
||||||
|
'@media (min-width: 601px)': {
|
||||||
|
flexDirection: 'row'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<TimeElapsed
|
<TimeElapsed
|
||||||
startTime={timeEntry.startTime}
|
startTime={timeEntry.startTime}
|
||||||
endTime={timeEntry.endTime}
|
endTime={timeEntry.endTime}
|
||||||
/>
|
/>
|
||||||
<Menu shadow="md" width={200}>
|
<Box
|
||||||
<Menu.Target>
|
sx={{
|
||||||
<ActionIcon title="Edit" mr="xs">
|
display: 'flex',
|
||||||
<Settings size={14} />
|
flexShrink: 0,
|
||||||
</ActionIcon>
|
|
||||||
</Menu.Target>
|
|
||||||
|
|
||||||
<Menu.Dropdown>
|
'@media (max-width: 600px)': {
|
||||||
<Menu.Label>Edit time entry</Menu.Label>
|
marginTop: '0.33rem'
|
||||||
<Menu.Item
|
}
|
||||||
component={Link}
|
}}
|
||||||
to={`/time-entries/${timeEntry.id}`}
|
>
|
||||||
icon={
|
<Menu shadow="md" width={200}>
|
||||||
<Edit3 size={14} color={theme.colors.yellow[8]} />
|
<Menu.Target>
|
||||||
}
|
<ActionIcon
|
||||||
>
|
title="Edit"
|
||||||
Edit
|
mr="xs"
|
||||||
</Menu.Item>
|
sx={{
|
||||||
|
marginLeft: 'auto'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Settings size={14} />
|
||||||
|
</ActionIcon>
|
||||||
|
</Menu.Target>
|
||||||
|
|
||||||
|
<Menu.Dropdown>
|
||||||
|
<Menu.Label>Edit time entry</Menu.Label>
|
||||||
|
<Menu.Item
|
||||||
|
component={Link}
|
||||||
|
to={`/time-entries/${timeEntry.id}`}
|
||||||
|
icon={
|
||||||
|
<Edit3 size={14} color={theme.colors.yellow[8]} />
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Menu.Item>
|
||||||
|
<Form
|
||||||
|
method="delete"
|
||||||
|
action={`/time-entries/${timeEntry.id}`}
|
||||||
|
>
|
||||||
|
<Menu.Item
|
||||||
|
component="button"
|
||||||
|
type="submit"
|
||||||
|
icon={
|
||||||
|
<Trash size={14} color={theme.colors.red[8]} />
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</Menu.Item>
|
||||||
|
</Form>
|
||||||
|
</Menu.Dropdown>
|
||||||
|
</Menu>
|
||||||
|
{timeEntry.endTime ? (
|
||||||
|
<Form method="post" action="/time-entries/new">
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name="startTime"
|
||||||
|
value={new Date(Date.now()).toISOString()}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name="description"
|
||||||
|
value={timeEntry.description}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name="projectId"
|
||||||
|
value={timeEntry.projectId}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name="userId"
|
||||||
|
value={timeEntry.userId}
|
||||||
|
/>
|
||||||
|
<ActionIcon
|
||||||
|
type="submit"
|
||||||
|
title="Start new entry with same description"
|
||||||
|
>
|
||||||
|
<ThemeIcon variant="light">
|
||||||
|
<Play size={14} color={theme.colors.blue[7]} />
|
||||||
|
</ThemeIcon>
|
||||||
|
</ActionIcon>
|
||||||
|
</Form>
|
||||||
|
) : (
|
||||||
<Form
|
<Form
|
||||||
method="delete"
|
method="patch"
|
||||||
action={`/time-entries/${timeEntry.id}`}
|
action={`/time-entries/${timeEntry.id}`}
|
||||||
>
|
>
|
||||||
<Menu.Item
|
<input
|
||||||
component="button"
|
type="hidden"
|
||||||
|
name="endTime"
|
||||||
|
value={new Date().toISOString()}
|
||||||
|
/>
|
||||||
|
<ActionIcon
|
||||||
type="submit"
|
type="submit"
|
||||||
icon={<Trash size={14} color={theme.colors.red[8]} />}
|
variant="filled"
|
||||||
|
title="Stop"
|
||||||
|
style={{
|
||||||
|
backgroundColor: theme.colors.red[7],
|
||||||
|
color: 'white',
|
||||||
|
borderRadius: '50%'
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
Delete
|
<Square size={12} fill="currentColor" />
|
||||||
</Menu.Item>
|
</ActionIcon>
|
||||||
</Form>
|
</Form>
|
||||||
</Menu.Dropdown>
|
)}
|
||||||
</Menu>
|
</Box>
|
||||||
{timeEntry.endTime ? (
|
</Box>
|
||||||
<Form method="post" action="/time-entries/new">
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
name="startTime"
|
|
||||||
value={new Date(Date.now()).toISOString()}
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
name="description"
|
|
||||||
value={timeEntry.description}
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
name="projectId"
|
|
||||||
value={timeEntry.projectId}
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
name="userId"
|
|
||||||
value={timeEntry.userId}
|
|
||||||
/>
|
|
||||||
<ActionIcon
|
|
||||||
type="submit"
|
|
||||||
title="Start new entry with same description"
|
|
||||||
>
|
|
||||||
<ThemeIcon variant="light">
|
|
||||||
<Play size={14} color={theme.colors.blue[7]} />
|
|
||||||
</ThemeIcon>
|
|
||||||
</ActionIcon>
|
|
||||||
</Form>
|
|
||||||
) : (
|
|
||||||
<Form
|
|
||||||
method="patch"
|
|
||||||
action={`/time-entries/${timeEntry.id}`}
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
name="endTime"
|
|
||||||
value={new Date().toISOString()}
|
|
||||||
/>
|
|
||||||
<ActionIcon
|
|
||||||
type="submit"
|
|
||||||
variant="filled"
|
|
||||||
title="Stop"
|
|
||||||
style={{
|
|
||||||
backgroundColor: theme.colors.red[7],
|
|
||||||
color: 'white',
|
|
||||||
borderRadius: '50%'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Square size={12} fill="currentColor" />
|
|
||||||
</ActionIcon>
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Paper>
|
</Paper>
|
||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue