style(frontend): mobile responsive polish for Dashboard/Providers/Upload/Reconciliation
This commit is contained in:
@@ -108,7 +108,7 @@ export function Dashboard() {
|
|||||||
const sectionBase = kpiBase + kpiStep * 5 + 60; // after the last KPI
|
const sectionBase = kpiBase + kpiStep * 5 + 60; // after the last KPI
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-10">
|
<div className="space-y-6 md:space-y-10">
|
||||||
{/* Hero */}
|
{/* Hero */}
|
||||||
<header
|
<header
|
||||||
className="relative animate-fade-in overflow-hidden"
|
className="relative animate-fade-in overflow-hidden"
|
||||||
@@ -129,13 +129,13 @@ export function Dashboard() {
|
|||||||
{fmt.usd(kpis.billed)}
|
{fmt.usd(kpis.billed)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative z-10 flex items-end justify-between gap-6 flex-wrap">
|
<div className="relative z-10 flex items-end justify-between gap-4 sm:gap-6 flex-wrap">
|
||||||
<div>
|
<div className="min-w-0">
|
||||||
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
||||||
<span className="inline-block h-px w-6 bg-border" />
|
<span className="inline-block h-px w-6 bg-border" />
|
||||||
Today · {fmt.date(new Date().toISOString())}
|
Today · {fmt.date(new Date().toISOString())}
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-[28px] leading-[1.15] font-semibold tracking-tight">
|
<h1 className="text-[22px] sm:text-[28px] leading-[1.15] font-semibold tracking-tight">
|
||||||
Good morning, Jordan.
|
Good morning, Jordan.
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-muted-foreground mt-1.5 max-w-xl text-[14px] leading-relaxed">
|
<p className="text-muted-foreground mt-1.5 max-w-xl text-[14px] leading-relaxed">
|
||||||
@@ -157,7 +157,7 @@ export function Dashboard() {
|
|||||||
{/* KPIs — every card carries a trend. */}
|
{/* KPIs — every card carries a trend. */}
|
||||||
<section
|
<section
|
||||||
aria-label="Key performance indicators"
|
aria-label="Key performance indicators"
|
||||||
className="grid gap-4 grid-cols-2 lg:grid-cols-5"
|
className="grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5"
|
||||||
>
|
>
|
||||||
<KpiCard
|
<KpiCard
|
||||||
label="Claims"
|
label="Claims"
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ export function Providers() {
|
|||||||
const items = data?.items ?? [];
|
const items = data?.items ?? [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8 animate-fade-in">
|
<div className="space-y-6 md:space-y-8 animate-fade-in">
|
||||||
<header>
|
<header>
|
||||||
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
||||||
<span className="inline-block h-px w-6 bg-border" />
|
<span className="inline-block h-px w-6 bg-border" />
|
||||||
Providers
|
Providers
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-[22px] font-semibold tracking-tight">Provider directory</h1>
|
<h1 className="text-[22px] sm:text-[26px] font-semibold tracking-tight">Provider directory</h1>
|
||||||
<p className="text-muted-foreground mt-1.5 text-[14px]">
|
<p className="text-muted-foreground mt-1.5 text-[14px]">
|
||||||
NPIs registered with the clearinghouse for 837P submission and 835
|
NPIs registered with the clearinghouse for 837P submission and 835
|
||||||
remittance retrieval.
|
remittance retrieval.
|
||||||
@@ -49,7 +49,7 @@ export function Providers() {
|
|||||||
{items.map((p) => (
|
{items.map((p) => (
|
||||||
<article
|
<article
|
||||||
key={p.npi}
|
key={p.npi}
|
||||||
className="surface rounded-xl p-6 flex flex-col gap-4 hover:bg-muted/20 transition-colors"
|
className="surface rounded-xl p-4 sm:p-6 flex flex-col gap-4 hover:bg-muted/20 transition-colors"
|
||||||
>
|
>
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<div className="h-10 w-10 rounded-lg bg-muted/60 flex items-center justify-center text-foreground">
|
<div className="h-10 w-10 rounded-lg bg-muted/60 flex items-center justify-center text-foreground">
|
||||||
|
|||||||
@@ -27,17 +27,17 @@ export function ReconciliationPage() {
|
|||||||
|
|
||||||
if (unmatched.isLoading) {
|
if (unmatched.isLoading) {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8 animate-fade-in">
|
<div className="space-y-6 md:space-y-8 animate-fade-in">
|
||||||
<header>
|
<header>
|
||||||
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
||||||
<span className="inline-block h-px w-6 bg-border" />
|
<span className="inline-block h-px w-6 bg-border" />
|
||||||
Reconciliation
|
Reconciliation
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-[22px] font-semibold tracking-tight">
|
<h1 className="text-[22px] sm:text-[26px] font-semibold tracking-tight">
|
||||||
Manual pairing
|
Manual pairing
|
||||||
</h1>
|
</h1>
|
||||||
</header>
|
</header>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<Skeleton variant="default" height={320} />
|
<Skeleton variant="default" height={320} />
|
||||||
<Skeleton variant="default" height={320} />
|
<Skeleton variant="default" height={320} />
|
||||||
</div>
|
</div>
|
||||||
@@ -51,13 +51,13 @@ export function ReconciliationPage() {
|
|||||||
? unmatched.error.message
|
? unmatched.error.message
|
||||||
: String(unmatched.error);
|
: String(unmatched.error);
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8 animate-fade-in">
|
<div className="space-y-6 md:space-y-8 animate-fade-in">
|
||||||
<header>
|
<header>
|
||||||
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
||||||
<span className="inline-block h-px w-6 bg-border" />
|
<span className="inline-block h-px w-6 bg-border" />
|
||||||
Reconciliation
|
Reconciliation
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-[22px] font-semibold tracking-tight">
|
<h1 className="text-[22px] sm:text-[26px] font-semibold tracking-tight">
|
||||||
Manual pairing
|
Manual pairing
|
||||||
</h1>
|
</h1>
|
||||||
</header>
|
</header>
|
||||||
@@ -78,13 +78,13 @@ export function ReconciliationPage() {
|
|||||||
|
|
||||||
if (empty) {
|
if (empty) {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8 animate-fade-in">
|
<div className="space-y-6 md:space-y-8 animate-fade-in">
|
||||||
<header>
|
<header>
|
||||||
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
||||||
<span className="inline-block h-px w-6 bg-border" />
|
<span className="inline-block h-px w-6 bg-border" />
|
||||||
Reconciliation
|
Reconciliation
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-[22px] font-semibold tracking-tight">
|
<h1 className="text-[22px] sm:text-[26px] font-semibold tracking-tight">
|
||||||
Manual pairing
|
Manual pairing
|
||||||
</h1>
|
</h1>
|
||||||
</header>
|
</header>
|
||||||
@@ -125,13 +125,13 @@ export function ReconciliationPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8 animate-fade-in">
|
<div className="space-y-6 md:space-y-8 animate-fade-in">
|
||||||
<header>
|
<header>
|
||||||
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
||||||
<span className="inline-block h-px w-6 bg-border" />
|
<span className="inline-block h-px w-6 bg-border" />
|
||||||
Reconciliation
|
Reconciliation
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-[22px] font-semibold tracking-tight">
|
<h1 className="text-[22px] sm:text-[26px] font-semibold tracking-tight">
|
||||||
Manual pairing
|
Manual pairing
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-muted-foreground mt-1.5 text-[14px]">
|
<p className="text-muted-foreground mt-1.5 text-[14px]">
|
||||||
@@ -139,7 +139,7 @@ export function ReconciliationPage() {
|
|||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
{/* Claims column */}
|
{/* Claims column */}
|
||||||
<div className="surface rounded-xl border border-border/60 p-4 space-y-2">
|
<div className="surface rounded-xl border border-border/60 p-4 space-y-2">
|
||||||
<h2 className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
<h2 className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
||||||
@@ -155,7 +155,7 @@ export function ReconciliationPage() {
|
|||||||
onClick={() => setSelectedClaim(c.id)}
|
onClick={() => setSelectedClaim(c.id)}
|
||||||
aria-pressed={active}
|
aria-pressed={active}
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-full text-left p-3 rounded-md border transition-colors",
|
"w-full text-left p-3 min-h-[44px] rounded-md border transition-colors",
|
||||||
active
|
active
|
||||||
? "border-accent bg-accent/5"
|
? "border-accent bg-accent/5"
|
||||||
: "border-border/60 hover:border-border"
|
: "border-border/60 hover:border-border"
|
||||||
@@ -190,7 +190,7 @@ export function ReconciliationPage() {
|
|||||||
onClick={() => setSelectedRemit(r.id)}
|
onClick={() => setSelectedRemit(r.id)}
|
||||||
aria-pressed={active}
|
aria-pressed={active}
|
||||||
className={cn(
|
className={cn(
|
||||||
"w-full text-left p-3 rounded-md border transition-colors",
|
"w-full text-left p-3 min-h-[44px] rounded-md border transition-colors",
|
||||||
active
|
active
|
||||||
? "border-accent bg-accent/5"
|
? "border-accent bg-accent/5"
|
||||||
: "border-border/60 hover:border-border"
|
: "border-border/60 hover:border-border"
|
||||||
@@ -215,10 +215,11 @@ export function ReconciliationPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
<Button
|
<Button
|
||||||
onClick={handleMatch}
|
onClick={handleMatch}
|
||||||
disabled={!selectedClaim || !selectedRemit || match.isPending}
|
disabled={!selectedClaim || !selectedRemit || match.isPending}
|
||||||
|
className="min-h-[44px] sm:min-h-0"
|
||||||
>
|
>
|
||||||
<GitMerge className="h-3.5 w-3.5 mr-1.5" />
|
<GitMerge className="h-3.5 w-3.5 mr-1.5" />
|
||||||
Match selected
|
Match selected
|
||||||
@@ -227,12 +228,13 @@ export function ReconciliationPage() {
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={handleClear}
|
onClick={handleClear}
|
||||||
disabled={(!selectedClaim && !selectedRemit) || match.isPending}
|
disabled={(!selectedClaim && !selectedRemit) || match.isPending}
|
||||||
|
className="min-h-[44px] sm:min-h-0"
|
||||||
>
|
>
|
||||||
<X className="h-3.5 w-3.5 mr-1.5" />
|
<X className="h-3.5 w-3.5 mr-1.5" />
|
||||||
Clear selection
|
Clear selection
|
||||||
</Button>
|
</Button>
|
||||||
{selectedClaim || selectedRemit ? (
|
{selectedClaim || selectedRemit ? (
|
||||||
<span className="text-xs text-muted-foreground ml-2">
|
<span className="text-xs text-muted-foreground sm:ml-2 basis-full sm:basis-auto">
|
||||||
{selectedClaim ? `Claim ${selectedClaim}` : "No claim"}
|
{selectedClaim ? `Claim ${selectedClaim}` : "No claim"}
|
||||||
{" · "}
|
{" · "}
|
||||||
{selectedRemit ? `Remit ${selectedRemit}` : "No remit"}
|
{selectedRemit ? `Remit ${selectedRemit}` : "No remit"}
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ function ClaimCard837({ claim }: { claim: ClaimOutput }) {
|
|||||||
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-1.5">
|
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-1.5">
|
||||||
Service lines
|
Service lines
|
||||||
</div>
|
</div>
|
||||||
<div className="rounded-md border border-border/40 overflow-hidden">
|
<div className="rounded-md border border-border/40 overflow-x-auto">
|
||||||
<table className="w-full text-[12px]">
|
<table className="w-full text-[12px]">
|
||||||
<thead className="bg-muted/30">
|
<thead className="bg-muted/30">
|
||||||
<tr className="text-left text-muted-foreground">
|
<tr className="text-left text-muted-foreground">
|
||||||
@@ -403,7 +403,7 @@ function ClaimCard835({ claim }: { claim: ClaimPayment }) {
|
|||||||
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-1.5">
|
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-1.5">
|
||||||
Service payments
|
Service payments
|
||||||
</div>
|
</div>
|
||||||
<div className="rounded-md border border-border/40 overflow-hidden">
|
<div className="rounded-md border border-border/40 overflow-x-auto">
|
||||||
<table className="w-full text-[12px]">
|
<table className="w-full text-[12px]">
|
||||||
<thead className="bg-muted/30">
|
<thead className="bg-muted/30">
|
||||||
<tr className="text-left text-muted-foreground">
|
<tr className="text-left text-muted-foreground">
|
||||||
@@ -584,13 +584,13 @@ export function Upload() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8 animate-fade-in">
|
<div className="space-y-6 md:space-y-8 animate-fade-in">
|
||||||
<header>
|
<header>
|
||||||
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
<div className="text-[10.5px] font-semibold uppercase tracking-[0.18em] text-muted-foreground mb-2 flex items-center gap-2">
|
||||||
<span className="inline-block h-px w-6 bg-border" />
|
<span className="inline-block h-px w-6 bg-border" />
|
||||||
Upload · EDI parser
|
Upload · EDI parser
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-[22px] font-semibold tracking-tight">
|
<h1 className="text-[22px] sm:text-[26px] font-semibold tracking-tight">
|
||||||
Parse an X12 file
|
Parse an X12 file
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-muted-foreground mt-1.5 text-[14px] max-w-2xl">
|
<p className="text-muted-foreground mt-1.5 text-[14px] max-w-2xl">
|
||||||
@@ -665,7 +665,7 @@ export function Upload() {
|
|||||||
if (e.key === "Enter" || e.key === " ") inputRef.current?.click();
|
if (e.key === "Enter" || e.key === " ") inputRef.current?.click();
|
||||||
}}
|
}}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-border/60 bg-muted/20 px-6 py-8 cursor-pointer transition-colors",
|
"relative flex flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-border/60 bg-muted/20 px-6 py-10 sm:py-8 min-h-[140px] sm:min-h-[120px] cursor-pointer transition-colors",
|
||||||
"hover:bg-muted/30 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
"hover:bg-muted/30 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -704,7 +704,7 @@ export function Upload() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-between gap-3">
|
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<div className="text-[12px] text-muted-foreground">
|
<div className="text-[12px] text-muted-foreground">
|
||||||
{api.isConfigured ? (
|
{api.isConfigured ? (
|
||||||
<span className="inline-flex items-center gap-1.5">
|
<span className="inline-flex items-center gap-1.5">
|
||||||
@@ -721,12 +721,13 @@ export function Upload() {
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
{file ? (
|
{file ? (
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => pickFile(null)}
|
onClick={() => pickFile(null)}
|
||||||
disabled={running}
|
disabled={running}
|
||||||
|
className="min-h-[44px] sm:min-h-0"
|
||||||
>
|
>
|
||||||
Clear
|
Clear
|
||||||
</Button>
|
</Button>
|
||||||
@@ -734,6 +735,7 @@ export function Upload() {
|
|||||||
<Button
|
<Button
|
||||||
onClick={onParse}
|
onClick={onParse}
|
||||||
disabled={!file || running}
|
disabled={!file || running}
|
||||||
|
className="min-h-[44px] sm:min-h-0"
|
||||||
>
|
>
|
||||||
{running ? (
|
{running ? (
|
||||||
<>
|
<>
|
||||||
|
|||||||
Reference in New Issue
Block a user