diff --git a/main.py b/main.py index ac9696b..2a0fabc 100644 --- a/main.py +++ b/main.py @@ -107,9 +107,40 @@ def list_projects(): return projects +@app.post("/preview-time") +async def preview_time_from_csv(file: UploadFile = File(...)): + """ + Parse a file and return the extracted work time without submitting. + """ + content = await file.read() + filename = (file.filename or "").lower() + content_type = (file.content_type or "").lower() + + try: + if filename.endswith(".xlsx") or "spreadsheetml" in content_type: + rows = parse_xlsx(content) + else: + rows = parse_csv(content.decode('utf-8-sig')) + except ValueError as e: + raise HTTPException(status_code=400, detail=str(e)) + except Exception as e: + raise HTTPException(status_code=400, detail=f"Failed to parse file: {str(e)}") + + work_time = extract_work_time(rows) + + if not work_time: + raise HTTPException( + status_code=400, + detail="No valid work time found in the uploaded file." + ) + + return [{"date": k, "hours": v} for k, v in sorted(work_time.items())] + + @app.post("/report-time", response_model=TimeReportResponse) async def report_time_from_csv( project_name: str, + excluded_dates: str = "", file: UploadFile = File(...) ): """ @@ -168,10 +199,14 @@ async def report_time_from_csv( work_time = extract_work_time(rows) + if excluded_dates: + excluded_list = [d.strip() for d in excluded_dates.split(",")] + work_time = {k: v for k, v in work_time.items() if k not in excluded_list} + if not work_time: raise HTTPException( status_code=400, - detail="No valid work time found in the uploaded CSV." + detail="No valid work time found in the uploaded CSV after filtering." ) # Submit events diff --git a/static/css/style.css b/static/css/style.css index 0198f83..091492e 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -242,6 +242,62 @@ body::before { color: var(--text-muted); } +.text-sm { + font-size: 0.875rem; +} + +.text-muted { + color: var(--text-muted); +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.table-responsive { + overflow-x: auto; +} + +.preview-table { + width: 100%; + border-collapse: collapse; + margin-top: 0.5rem; + background: rgba(255, 255, 255, 0.02); + border: 1px solid var(--border); + border-radius: var(--radius); + overflow: hidden; +} + +.preview-table th, .preview-table td { + padding: 0.75rem 1rem; + text-align: left; + border-bottom: 1px solid var(--border); +} + +.preview-table th { + background: rgba(255, 255, 255, 0.04); + font-weight: 600; + color: var(--text-primary); +} + +.preview-table tr { + transition: var(--transition); + cursor: pointer; +} + +.preview-table tbody tr:hover { + background: rgba(255, 255, 255, 0.06); +} + +.preview-table tbody tr.excluded { + opacity: 0.5; + background: rgba(239, 68, 68, 0.05); +} + +.preview-table tbody tr.excluded td { + text-decoration: line-through; +} + /* File Preview */ .file-preview { margin-top: 1.5rem; diff --git a/static/index.html b/static/index.html index a9312c5..d07d3f5 100644 --- a/static/index.html +++ b/static/index.html @@ -4,7 +4,7 @@
Processing your request...