fix(timesheet): extend mobile layout to xl and tighten row field widths
This commit is contained in:
@@ -1235,11 +1235,11 @@ function EntryEditorFields({
|
||||
onChange={(projectId) => (onProjectChange ? onProjectChange(projectId) : onChange({ projectId }))}
|
||||
placeholder={t.timesheet?.projectLabel || "Project"}
|
||||
portalOwnerId={portalOwnerId}
|
||||
className="min-w-0 max-w-[150px] 2xl:max-w-max flex-1"
|
||||
className="min-w-0 max-w-fit flex-1"
|
||||
/>
|
||||
|
||||
{selectedProject?.client?.name && (
|
||||
<span className="min-w-0 max-w-[120px] 2xl:max-w-max shrink truncate text-sm text-slate-400 dark:text-slate-500" title={selectedProject.client.name}>
|
||||
<span className="min-w-0 max-w-[120px] 2xl:max-w-fit shrink truncate text-sm text-slate-400 dark:text-slate-500" title={selectedProject.client.name}>
|
||||
- {selectedProject.client.name}
|
||||
</span>
|
||||
)}
|
||||
@@ -1748,7 +1748,7 @@ function MobileRecordedEntryCard({
|
||||
};
|
||||
|
||||
return (
|
||||
<div ref={wrapperRef} className="relative overflow-hidden border-b border-slate-200 bg-slate-100/70 dark:border-slate-800 dark:bg-slate-900/70 md:hidden">
|
||||
<div ref={wrapperRef} className="relative overflow-hidden border-b border-slate-200 bg-slate-100/70 dark:border-slate-800 dark:bg-slate-900/70 xl:hidden">
|
||||
<div className="pointer-events-none absolute inset-y-0 left-0 flex w-24 items-center justify-start bg-emerald-500/12 ps-4 text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-300">
|
||||
<Play className="h-4 w-4" />
|
||||
</div>
|
||||
@@ -2526,110 +2526,10 @@ export default function Timesheet() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
onBlurCapture={handleTimerBlurCapture}
|
||||
className="mb-4 hidden rounded-xl border border-slate-200 bg-white p-4 shadow-sm dark:border-slate-800 dark:bg-slate-950 md:block xl:hidden"
|
||||
>
|
||||
<div className="space-y-3">
|
||||
<Input
|
||||
value={timerDraft.description}
|
||||
placeholder={t.timesheet?.descriptionPlaceholder || "What are you working on?"}
|
||||
onChange={(event) => setTimerDraft((current) => ({ ...current, description: event.target.value }))}
|
||||
disabled={isStartingTimer}
|
||||
className="h-11 border-slate-200 bg-slate-50 text-sm dark:border-slate-700 dark:bg-slate-900"
|
||||
/>
|
||||
|
||||
<div className="grid gap-3 lg:grid-cols-[minmax(0,1fr)_minmax(180px,220px)_auto]">
|
||||
<Select
|
||||
value={timerDraft.projectId}
|
||||
onChange={(value) => setTimerDraft((current) => ({ ...current, projectId: String(value) }))}
|
||||
options={[
|
||||
{ value: "", label: t.timesheet?.projectLabel || "Project" },
|
||||
...runningTimerProjects.map((project) => ({ value: project.id, label: project.name })),
|
||||
]}
|
||||
className="w-full"
|
||||
buttonClassName="h-11 w-full rounded-md border border-slate-200 bg-slate-50 px-3 text-sm shadow-none outline-none dark:border-slate-700 dark:bg-slate-900 focus:ring-0 focus-visible:ring-0 focus-visible:ring-offset-0"
|
||||
disabled={isStartingTimer}
|
||||
portalOwnerId={timerEditorOwnerId}
|
||||
/>
|
||||
|
||||
<div className="flex min-w-0 items-center">
|
||||
<TagMultiSelect
|
||||
tags={runningTimerTags}
|
||||
selectedTags={timerDraft.tags}
|
||||
onToggleTag={(tagId) =>
|
||||
setTimerDraft((current) => ({ ...current, tags: toggleTagId(current.tags, tagId) }))
|
||||
}
|
||||
emptyHint={t.timesheet?.noTagsHint || "Create tags first from the Tags page."}
|
||||
title={t.tags?.title || "Tags"}
|
||||
compact
|
||||
portalOwnerId={timerEditorOwnerId}
|
||||
className="max-w-full"
|
||||
buttonClassName="max-w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-start lg:justify-end">
|
||||
<div className="flex h-11 min-w-[132px] items-center justify-center rounded-md border border-slate-200 bg-slate-50 px-4 text-sm font-semibold text-slate-900 dark:border-slate-700 dark:bg-slate-900 dark:text-white">
|
||||
{runningEntry ? formatDuration(runningEntry, ticker) : "00:00:00"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<BillableIconButton
|
||||
checked={timerDraft.isBillable}
|
||||
onChange={(checked) => setTimerDraft((current) => ({ ...current, isBillable: checked }))}
|
||||
label={t.timesheet?.billable || "Billable"}
|
||||
disabled={isStartingTimer}
|
||||
/>
|
||||
|
||||
<div className="flex shrink-0 items-center gap-2">
|
||||
{runningEntry ? (
|
||||
<>
|
||||
<Button
|
||||
variant="destructive"
|
||||
size="icon"
|
||||
onClick={() => void handleStop(runningEntry)}
|
||||
className="h-11 w-11 rounded-md"
|
||||
title={t.timesheet?.stopTimer || "Stop"}
|
||||
aria-label={t.timesheet?.stopTimer || "Stop"}
|
||||
>
|
||||
<Square className="h-4 w-4 fill-current" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="icon"
|
||||
onClick={openDiscardTimerModal}
|
||||
disabled={isDiscardingTimer}
|
||||
className="h-11 w-11 rounded-md"
|
||||
title={(t.actions as { discard?: string } | undefined)?.discard || "Discard"}
|
||||
aria-label={(t.actions as { discard?: string } | undefined)?.discard || "Discard"}
|
||||
>
|
||||
{isDiscardingTimer ? "..." : <Trash2 className="h-4 w-4" />}
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<Button
|
||||
onClick={() => void handleStartTimer()}
|
||||
disabled={isStartingTimer}
|
||||
size="icon"
|
||||
className="h-11 w-11 rounded-md"
|
||||
title={t.timesheet?.startTimer || "Start"}
|
||||
aria-label={t.timesheet?.startTimer || "Start"}
|
||||
>
|
||||
{isStartingTimer ? "..." : <Play className="h-4 w-4 fill-current" />}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
ref={mobileTimerRef}
|
||||
onBlurCapture={handleTimerBlurCapture}
|
||||
className="mb-4 rounded-xl border border-slate-200 bg-white p-3 shadow-sm dark:border-slate-800 dark:bg-slate-950 md:hidden"
|
||||
className="mb-4 rounded-xl border border-slate-200 bg-white p-3 shadow-sm dark:border-slate-800 dark:bg-slate-950 xl:hidden"
|
||||
>
|
||||
<div className="space-y-3">
|
||||
<Input
|
||||
@@ -2802,20 +2702,7 @@ export default function Timesheet() {
|
||||
lang={lang}
|
||||
/>
|
||||
</div>
|
||||
<div className="hidden md:block xl:hidden">
|
||||
<RecordedEntryCard
|
||||
entry={entry}
|
||||
t={t}
|
||||
projects={projects}
|
||||
tags={tags}
|
||||
onDelete={openDeleteModal}
|
||||
onRestart={handleRestartFromEntry}
|
||||
onEntryUpdated={handleEntryUpdated}
|
||||
variant="tablet"
|
||||
lang={lang}
|
||||
/>
|
||||
</div>
|
||||
<div className="md:hidden">
|
||||
<div className="xl:hidden">
|
||||
<MobileRecordedEntryCard
|
||||
entry={entry}
|
||||
t={t}
|
||||
|
||||
Reference in New Issue
Block a user