Update day-schedule layout (style improvements/fixes), attached delta badge to time input field
This commit is contained in:
@@ -185,8 +185,8 @@ const MedPlanAssistant = () => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="max-w-7xl mx-auto" style={{
|
<div className="max-w-7xl mx-auto" style={{
|
||||||
// TODO generally review layout for smaller screens
|
// TODO solution not ideal for mobile, consider https://tailwindcss.com/docs/responsive-design
|
||||||
minWidth: '410px'
|
minWidth: '480px'
|
||||||
}}>
|
}}>
|
||||||
<header className="mb-8">
|
<header className="mb-8">
|
||||||
<div className="flex justify-between items-start gap-4">
|
<div className="flex justify-between items-start gap-4">
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
|||||||
// Calculate time delta from previous intake (across all days)
|
// Calculate time delta from previous intake (across all days)
|
||||||
const calculateTimeDelta = (dayIndex: number, doseIndex: number): string => {
|
const calculateTimeDelta = (dayIndex: number, doseIndex: number): string => {
|
||||||
if (dayIndex === 0 && doseIndex === 0) {
|
if (dayIndex === 0 && doseIndex === 0) {
|
||||||
return '+0:00'; // First dose of all days
|
return ""; // No delta for first dose of first day
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentDay = days[dayIndex];
|
const currentDay = days[dayIndex];
|
||||||
@@ -224,8 +224,7 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME incomplete implementation of @container and @min-[497px]:
|
// FIXME incomplete implementation of @container and @min-[497px]:
|
||||||
// the intention is to wrap dose buttons as well as header badges all at the same time
|
// TODO solution not ideal for mobile, consider https://tailwindcss.com/docs/responsive-design
|
||||||
// at a specific container width while adding a spacer to align buttons with time field
|
|
||||||
return (
|
return (
|
||||||
<Card key={day.id} className="@container">
|
<Card key={day.id} className="@container">
|
||||||
<CollapsibleCardHeader
|
<CollapsibleCardHeader
|
||||||
@@ -258,7 +257,7 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="flex flex-nowrap items-center gap-2">
|
<div className="flex flex-nowrap items-center gap-2">
|
||||||
<Badge variant="secondary" className="text-xs">
|
<Badge variant="solid" className="text-xs font-bold">
|
||||||
{t('day')} {dayIndex + 1}
|
{t('day')} {dayIndex + 1}
|
||||||
</Badge>
|
</Badge>
|
||||||
{!day.isTemplate && doseCountDiff !== 0 ? (
|
{!day.isTemplate && doseCountDiff !== 0 ? (
|
||||||
@@ -339,6 +338,8 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</CollapsibleCardHeader>
|
</CollapsibleCardHeader>
|
||||||
|
|
||||||
|
{/* Daily details (intakes) */}
|
||||||
{!collapsedDays.has(day.id) && (
|
{!collapsedDays.has(day.id) && (
|
||||||
<CardContent className="space-y-3">
|
<CardContent className="space-y-3">
|
||||||
{/* Daily total warning/error box */}
|
{/* Daily total warning/error box */}
|
||||||
@@ -352,11 +353,11 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* Dose table header */}
|
{/* Dose table header */}
|
||||||
<div className="flex flex-nowrap items-center gap-2 text-sm font-medium text-muted-foreground">
|
<div className="grid items-center gap-0.5 text-sm font-medium text-muted-foreground" style={{gridTemplateColumns: '20px 172px 72px 1fr'}}>
|
||||||
<div className="w-5 h-6 flex justify-center">#</div>{/* Index header */}
|
<div className="flex justify-center">#</div>{/* Index header */}
|
||||||
<div>{t('time')}</div>{/* Time header */}
|
<div>{t('time')}</div>{/* Time header */}
|
||||||
<div className="w-[8.5rem]"></div> {/* Spacer for delta badge */}
|
|
||||||
<div>{t('ldx')} (mg)</div>{/* LDX header */}
|
<div>{t('ldx')} (mg)</div>{/* LDX header */}
|
||||||
|
<div></div>{/* Buttons column (empty header) */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Dose rows */}
|
{/* Dose rows */}
|
||||||
@@ -392,14 +393,17 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={dose.id} className="space-y-2">
|
<div key={dose.id} className="space-y-2">
|
||||||
<div className="flex flex-nowrap @min-[497px]:flex-wrap items-center gap-2">
|
<div className="grid items-center gap-0.5" style={{gridTemplateColumns: '20px 172px 72px 1fr'}}>
|
||||||
<div className="flex flex-nowrap items-center gap-2">
|
{/* Intake index badge */}
|
||||||
{/* Intake index badges */}
|
<div className="flex justify-center">
|
||||||
<Badge variant="outline" className="text-xs w-5 h-6 flex items-center justify-center px-1.5">
|
<Badge variant="solid"
|
||||||
|
className="text-xs w-5 h-6 flex items-center justify-center px-1.5">
|
||||||
{doseIndex}
|
{doseIndex}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Time input */}
|
{/* Time input with delta badge attached (where applicable) */}
|
||||||
|
<div className="flex flex-nowrap items-center justify-center gap-0">
|
||||||
<FormTimeInput
|
<FormTimeInput
|
||||||
value={dose.time}
|
value={dose.time}
|
||||||
onChange={(value) => onUpdateDose(day.id, dose.id, 'time', value)}
|
onChange={(value) => onUpdateDose(day.id, dose.id, 'time', value)}
|
||||||
@@ -409,11 +413,10 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
|||||||
errorMessage={formatText(t('errorTimeRequired'))}
|
errorMessage={formatText(t('errorTimeRequired'))}
|
||||||
warningMessage={formatText(t('warningDuplicateTime'))}
|
warningMessage={formatText(t('warningDuplicateTime'))}
|
||||||
/>
|
/>
|
||||||
|
<Badge variant={timeDelta ? "field" : "transparent"} className="rounded-l-none border-l-0 font-light italic text-muted-foreground text-xs w-12 h-6 flex justify-end px-1.5">
|
||||||
{/* Delta badge */}
|
|
||||||
<Badge variant="outline" className="text-xs w-12 h-6 flex items-center justify-end px-1.5">
|
|
||||||
{timeDelta}
|
{timeDelta}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* LDX dose input */}
|
{/* LDX dose input */}
|
||||||
<FormNumericInput
|
<FormNumericInput
|
||||||
@@ -430,12 +433,9 @@ const DaySchedule: React.FC<DayScheduleProps> = ({
|
|||||||
warningMessage={doseWarningMessage}
|
warningMessage={doseWarningMessage}
|
||||||
inputWidth="w-[72px]"
|
inputWidth="w-[72px]"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Action buttons */}
|
{/* Action buttons - right aligned */}
|
||||||
<div className="flex flex-nowrap items-center gap-2">
|
<div className="flex flex-nowrap items-center justify-end gap-1">
|
||||||
{/* Spacer to align buttons in case of flex wrap only */}
|
|
||||||
<div className="w-0 @min-[497px]:w-5 h-9" />
|
|
||||||
<IconButtonWithTooltip
|
<IconButtonWithTooltip
|
||||||
onClick={() => handleActionWithSort(day.id, () => onUpdateDoseField(day.id, dose.id, 'isFed', !dose.isFed))}
|
onClick={() => handleActionWithSort(day.id, () => onUpdateDoseField(day.id, dose.id, 'isFed', !dose.isFed))}
|
||||||
icon={<Utensils className="h-4 w-4" />}
|
icon={<Utensils className="h-4 w-4" />}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import {
|
|||||||
} from './ui/tooltip';
|
} from './ui/tooltip';
|
||||||
import { useElementSize } from '../hooks/useElementSize';
|
import { useElementSize } from '../hooks/useElementSize';
|
||||||
|
|
||||||
|
// TODO make use of the actual theme colors;some colors are not matching the classes in the comments
|
||||||
// Chart color scheme
|
// Chart color scheme
|
||||||
const CHART_COLORS = {
|
const CHART_COLORS = {
|
||||||
// d-Amphetamine profiles
|
// d-Amphetamine profiles
|
||||||
@@ -42,7 +43,7 @@ const CHART_COLORS = {
|
|||||||
|
|
||||||
// Reference lines
|
// Reference lines
|
||||||
regularPlanDivider: '#22c55e', // green-500
|
regularPlanDivider: '#22c55e', // green-500
|
||||||
deviationDayDivider: '#9ca3af', // gray-400
|
deviationDayDivider: '#f59e0b', // yellow-500
|
||||||
therapeuticMin: '#22c55e', // green-500
|
therapeuticMin: '#22c55e', // green-500
|
||||||
therapeuticMax: '#ef4444', // red-500
|
therapeuticMax: '#ef4444', // red-500
|
||||||
dayDivider: '#9ca3af', // gray-400
|
dayDivider: '#9ca3af', // gray-400
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { cva, type VariantProps } from "class-variance-authority"
|
|||||||
import { cn } from "../../lib/utils"
|
import { cn } from "../../lib/utils"
|
||||||
|
|
||||||
const badgeVariants = cva(
|
const badgeVariants = cva(
|
||||||
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
"inline-flex items-center rounded-sm border px-2 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
@@ -16,7 +16,9 @@ const badgeVariants = cva(
|
|||||||
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
||||||
outline: "text-foreground",
|
outline: "text-foreground",
|
||||||
transparent: "border-transparent bg-transparent text-foreground hover:border-secondary",
|
transparent: "border-transparent bg-transparent text-foreground hover:border-secondary",
|
||||||
inverted: "border-transparent bg-muted-foreground text-background",
|
field: "bg-background text-foreground",
|
||||||
|
solid: "border-transparent bg-muted-foreground text-background",
|
||||||
|
solidmuted: "border-transparent bg-muted-foreground text-background",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { Clock } from "lucide-react"
|
|||||||
import { Button } from "./button"
|
import { Button } from "./button"
|
||||||
import { Input } from "./input"
|
import { Input } from "./input"
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from "./popover"
|
import { Popover, PopoverContent, PopoverTrigger } from "./popover"
|
||||||
|
import { Badge } from './badge';
|
||||||
import { cn } from "../../lib/utils"
|
import { cn } from "../../lib/utils"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user