Dr-Swopt 1 semana atrás
pai
commit
a32b7e76b5

+ 35 - 0
ai-data-entry-ui/src/app/components/claim-form/claim-form.component.css

@@ -7,6 +7,10 @@
     font-family: 'Inter', sans-serif;
 }
 
+.split-screen-container > div {
+    min-width: 0; /* Prevents grid children from overflowing */
+}
+
 .receipt-container {
     padding: 2rem;
     border-right: 1px solid var(--border-color);
@@ -14,6 +18,13 @@
     background: #f8fafc;
 }
 
+.form-container {
+    padding: 3rem 2rem; /* Reduced horizontal padding */
+    overflow-y: auto;
+    width: 100%;
+    box-sizing: border-box;
+}
+
 .form-header {
     margin-bottom: 2rem;
 }
@@ -25,6 +36,30 @@
     margin-bottom: 1rem;
 }
 
+@media (max-width: 1024px) {
+    .split-screen-container {
+        grid-template-columns: 1fr;
+        height: auto;
+        min-height: 100vh;
+    }
+    
+    .receipt-container {
+        border-right: none;
+        border-bottom: 1px solid var(--border-color);
+        height: auto;
+    }
+    
+    .form-container {
+        padding: 2rem;
+    }
+}
+
+@media (max-width: 600px) {
+    .financial-row {
+        grid-template-columns: 1fr;
+    }
+}
+
 .read-only-box {
     padding: 0.75rem;
     background: #f1f5f9;

+ 24 - 0
ai-data-entry-ui/src/app/components/claims-dashboard/claims-dashboard.component.css

@@ -323,6 +323,30 @@ h1 { font-size: 2rem; margin: 0; color: var(--text-primary); }
 .icon-small { width: 20px; height: 20px; }
 .icon-medium { width: 24px; height: 24px; }
 
+.actions-cell {
+    display: flex;
+    align-items: center;
+    gap: 12px;
+}
+
+.delete-icon-btn {
+    background: transparent;
+    border: none;
+    color: #94a3b8;
+    cursor: pointer;
+    padding: 4px;
+    border-radius: 4px;
+    transition: all 0.2s;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.delete-icon-btn:hover {
+    background: #fee2e2;
+    color: #ef4444;
+}
+
 .mock-receipt-view {
     min-height: 400px;
     display: flex;

+ 5 - 2
ai-data-entry-ui/src/app/components/claims-dashboard/claims-dashboard.component.html

@@ -90,8 +90,11 @@
                 Manual Entry
               </span>
             </td>
-            <td>
-               <lucide-icon [name]="ExternalLink" class="icon-tiny"></lucide-icon>
+            <td class="actions-cell">
+               <lucide-icon [name]="ExternalLink" class="icon-tiny" title="View Audit"></lucide-icon>
+               <button class="delete-icon-btn" (click)="deleteClaim($event, claim.id)" title="Delete Claim">
+                  <lucide-icon [name]="Trash2" class="icon-tiny"></lucide-icon>
+               </button>
             </td>
           </tr>
         </tbody>

+ 28 - 1
ai-data-entry-ui/src/app/components/claims-dashboard/claims-dashboard.component.ts

@@ -4,7 +4,7 @@ import { Router, RouterModule } from '@angular/router';
 import { ExtractionService } from '../../services/extraction.service';
 import { SessionService, User } from '../../services/session.service';
 import { ClaimRecord } from '../../services/extraction';
-import { LucideAngularModule, LogOut, Plus, UserCog, ExternalLink, X, FileText } from 'lucide-angular';
+import { LucideAngularModule, LogOut, Plus, UserCog, ExternalLink, X, FileText, Trash2 } from 'lucide-angular';
 
 @Component({
   selector: 'app-dashboard',
@@ -26,6 +26,7 @@ export class DashboardComponent implements OnInit {
   readonly ExternalLink = ExternalLink;
   readonly X = X;
   readonly FileText = FileText;
+  readonly Trash2 = Trash2;
 
   constructor(
     private extractionService: ExtractionService,
@@ -53,6 +54,32 @@ export class DashboardComponent implements OnInit {
     });
   }
 
+  deleteClaim(event: Event, claimId: string): void {
+    event.stopPropagation();
+    
+    if (confirm('Are you sure you want to delete this claim? The medical allowance will be refunded.')) {
+      this.extractionService.deleteClaim(claimId).subscribe({
+        next: () => {
+          this.loadClaims();
+          // Update current user balance if they are logged in
+          if (this.currentUser) {
+            this.extractionService.getUsers().subscribe(users => {
+              const updated = users.find(u => u.id === this.currentUser?.id);
+              if (updated) {
+                this.sessionService.setCurrentUser(updated);
+                this.currentUser = updated;
+              }
+            });
+          }
+        },
+        error: (err) => {
+          console.error('Delete failed:', err);
+          alert('Failed to delete claim.');
+        }
+      });
+    }
+  }
+
   viewDetail(claim: ClaimRecord): void {
     this.selectedClaim = claim;
   }

+ 7 - 0
ai-data-entry-ui/src/app/services/extraction.service.ts

@@ -55,6 +55,13 @@ export class ExtractionService {
       );
   }
 
+  deleteClaim(claimId: string): Observable<any> {
+    return this.http.delete(`${this.apiUrl}/claims/${claimId}`)
+      .pipe(
+        catchError(this.handleError)
+      );
+  }
+
   private handleError(error: HttpErrorResponse) {
     let errorMessage = 'An unknown error occurred!';
     if (error.error instanceof ErrorEvent) {

+ 5 - 0
ai-data-entry-ui/src/styles.css

@@ -10,9 +10,14 @@
   --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
 }
 
+*, *::before, *::after {
+  box-sizing: border-box;
+}
+
 body {
   background-color: var(--bg-primary);
   color: var(--text-primary);
   margin: 0;
   font-family: 'Inter', system-ui, -apple-system, sans-serif;
+  overflow-x: hidden;
 }

+ 21 - 0
backend/main.py

@@ -100,6 +100,27 @@ async def submit_claim(
     CLAIMS_DB.append(claim)
     return claim
 
+@app.delete("/api/v1/claims/{claim_id}")
+async def delete_claim(claim_id: str):
+    global CLAIMS_DB, USERS_DB
+    
+    # 1. Find the claim
+    claim_index = next((i for i, c in enumerate(CLAIMS_DB) if c.id == claim_id), -1)
+    if claim_index == -1:
+        raise HTTPException(status_code=404, detail="Claim not found")
+    
+    deleted_claim = CLAIMS_DB[claim_index]
+    
+    # 2. Refund the user's allowance if user exists
+    user = next((u for u in USERS_DB if u.name == deleted_claim.submitted_by), None)
+    if user:
+        user.medical_allowance += deleted_claim.amount_claimed
+        
+    # 3. Remove from list
+    CLAIMS_DB.pop(claim_index)
+    
+    return {"status": "success", "message": "Claim deleted and allowance refunded"}
+
 @app.get("/api/v1/claims", response_model=List[ClaimRecord])
 async def get_claims():
     return CLAIMS_DB