-
Notifications
You must be signed in to change notification settings - Fork 0
fix: Dashboard UI polish — remove redundant criteria icons, clean up form layout, guard submit #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,8 +5,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ArrowLeft, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Check, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| X, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| XCircle, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| X, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| AlertCircle, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| AlertTriangle, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| CheckCircle2, | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -155,9 +154,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| {met === null && <AlertCircle className="w-3.5 h-3.5" />} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <span className="text-sm text-foreground flex-1">{label}</span> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {met === true && <CheckCircle2 className="w-5 h-5 text-green-500 flex-shrink-0" />} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {met === false && <XCircle className="w-5 h-5 text-red-500 flex-shrink-0" />} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {met === null && <AlertCircle className="w-5 h-5 text-amber-500 flex-shrink-0" />} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <span className={cn('text-[10px] font-bold uppercase tracking-wide px-2 py-0.5 rounded-md flex-shrink-0', style.text, style.bg)}>{style.statusLabel}</span> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {isEditing && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <span className="text-xs text-muted-foreground">Toggle</span> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -276,7 +273,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| const id = transactionId; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if (submittedRef.current) return; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const elapsed = Math.floor((Date.now() - enteredAtRef.current) / 1000); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Check warning on line 276 in apps/dashboard/src/routes/analysis.$transactionId.tsx
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| if (elapsed > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| addReviewTimeMutation.mutate({ id, seconds: elapsed }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -456,6 +453,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| const displayData = isEditing ? editedData : effectiveRequest; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const hasUnmetCriteria = (effectiveRequest.criteria || []).some((c: { met: boolean | null }) => c.met !== true); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const isLowConfidence = effectiveRequest.status === 'ready' && effectiveRequest.confidence < LOW_CONFIDENCE_THRESHOLD; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const canSubmit = effectiveRequest.status !== 'draft' && !!effectiveRequest.clinicalSummary?.trim(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="p-6 space-y-6 animate-fade-in"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -602,8 +600,8 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| </button> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <button | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={handleSubmit} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| disabled={isSubmitting || showSubmissionOverlay} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| className="px-5 py-2.5 text-sm font-semibold bg-teal text-white rounded-xl hover:bg-teal/90 disabled:opacity-70 transition-all shadow-teal flex items-center gap-2 min-w-[160px] justify-center click-effect-primary" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| disabled={!canSubmit || isSubmitting || showSubmissionOverlay} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| className="px-5 py-2.5 text-sm font-semibold bg-teal text-white rounded-xl hover:bg-teal/90 disabled:opacity-50 disabled:cursor-not-allowed transition-all shadow-teal flex items-center gap-2 min-w-[160px] justify-center click-effect-primary" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
602
to
605
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Disabled header submit button lacks a reason. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
| {(isSubmitting || showSubmissionOverlay) ? ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -684,7 +682,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="flex items-center justify-between mb-5"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <h2 className="font-bold text-foreground flex items-center gap-2"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <FileText className="w-5 h-5 text-teal" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| PA Form Data | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Clinical Details | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </h2> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <span className="flex items-center gap-1.5 px-3 py-1 rounded-full bg-teal/10 text-teal text-xs font-semibold"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <Sparkles className="w-3 h-3" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -693,44 +691,19 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="grid grid-cols-2 gap-x-8"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <EditableField | ||||||||||||||||||||||||||||||||||||||||||||||||||
| label="Patient Name" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| value={request.patient.name} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onChange={() => {}} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| isEditing={false} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <EditableField | ||||||||||||||||||||||||||||||||||||||||||||||||||
| label="Date of Birth" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| value={request.patient.dob} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onChange={() => {}} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| isEditing={false} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <EditableField | ||||||||||||||||||||||||||||||||||||||||||||||||||
| label="Member ID" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| value={request.patient.memberId} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onChange={() => {}} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| isEditing={false} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| mono | ||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <EditableField | ||||||||||||||||||||||||||||||||||||||||||||||||||
| label="Diagnosis Code" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| value={`${displayData.diagnosisCode} - ${displayData.diagnosis}`} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <EditableField | ||||||||||||||||||||||||||||||||||||||||||||||||||
| label="Diagnosis Code" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| value={`${displayData.diagnosisCode} - ${displayData.diagnosis}`} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onChange={(v) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const parts = v.split(' - '); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| setEditedData({ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ...editedData, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| setEditedData({ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ...editedData, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| diagnosisCode: parts[0] || '', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| diagnosis: parts[1] || '' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+694
to
704
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid lossy split for Diagnosis Code. 🔧 Safer parse to preserve hyphens- const parts = v.split(' - ');
- setEditedData({
- ...editedData,
- diagnosisCode: parts[0] || '',
- diagnosis: parts[1] || ''
- });
+ const [code, ...rest] = v.split(' - ');
+ setEditedData({
+ ...editedData,
+ diagnosisCode: (code ?? '').trim(),
+ diagnosis: rest.join(' - ').trim()
+ });📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
| isEditing={isEditing} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <EditableField | ||||||||||||||||||||||||||||||||||||||||||||||||||
| label="Procedure Code" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| value={request.procedureCode} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onChange={() => {}} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| isEditing={false} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <EditableField | ||||||||||||||||||||||||||||||||||||||||||||||||||
| label="Service Date" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| value={displayData.serviceDate || ''} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -793,12 +766,14 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <p className={cn( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| 'text-center text-sm font-medium mt-4 p-3 rounded-lg', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| displayConfidence(effectiveRequest.confidence) >= 80 ? 'bg-success/10 text-success' : | ||||||||||||||||||||||||||||||||||||||||||||||||||
| displayConfidence(effectiveRequest.confidence) >= 60 ? 'bg-warning/10 text-warning' : | ||||||||||||||||||||||||||||||||||||||||||||||||||
| effectiveRequest.status === 'draft' ? 'bg-secondary text-muted-foreground' : | ||||||||||||||||||||||||||||||||||||||||||||||||||
| displayConfidence(effectiveRequest.confidence) >= 80 ? 'bg-success/10 text-success' : | ||||||||||||||||||||||||||||||||||||||||||||||||||
| displayConfidence(effectiveRequest.confidence) >= 60 ? 'bg-warning/10 text-warning' : | ||||||||||||||||||||||||||||||||||||||||||||||||||
| 'bg-destructive/10 text-destructive' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| )}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {displayConfidence(effectiveRequest.confidence) >= 80 ? 'High confidence — ready for submission' : | ||||||||||||||||||||||||||||||||||||||||||||||||||
| displayConfidence(effectiveRequest.confidence) >= 60 ? 'Medium confidence — review recommended' : | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {effectiveRequest.status === 'draft' ? 'Awaiting AI analysis — click Process to begin' : | ||||||||||||||||||||||||||||||||||||||||||||||||||
| displayConfidence(effectiveRequest.confidence) >= 80 ? 'High confidence — ready for submission' : | ||||||||||||||||||||||||||||||||||||||||||||||||||
| displayConfidence(effectiveRequest.confidence) >= 60 ? 'Medium confidence — review recommended' : | ||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Low confidence — manual review required'} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </p> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -867,14 +842,19 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="space-y-3"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <button | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={handleSubmit} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| disabled={isSubmitting || showSubmissionOverlay} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| className="w-full px-5 py-3.5 text-sm font-semibold bg-teal text-white rounded-xl hover:bg-teal/90 disabled:opacity-70 transition-all shadow-teal flex items-center justify-center gap-2 click-effect-primary" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| disabled={!canSubmit || isSubmitting || showSubmissionOverlay} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| className="w-full px-5 py-3.5 text-sm font-semibold bg-teal text-white rounded-xl hover:bg-teal/90 disabled:opacity-50 disabled:cursor-not-allowed transition-all shadow-teal flex items-center justify-center gap-2 click-effect-primary" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {(isSubmitting || showSubmissionOverlay) ? ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <LoadingSpinner size="sm" className="border-white border-t-transparent" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <span>Submitting to athenahealth...</span> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) : !canSubmit ? ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <AlertCircle className="w-4 h-4" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Process request before submitting | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) : ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <Send className="w-4 h-4" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard
handleSubmitwithcanSubmit.Line 456 introduces the new gate, but
handleSubmitcan still be triggered programmatically even whencanSubmitis false. Add an early return to enforce the gate in code, not just UI.✅ Suggested guard near
handleSubmit🤖 Prompt for AI Agents