React + Django ~8 Hours Intermediate

What You Are Building

Build an expense submission and approval system with file uploads.

This project teaches

  • Django model design
  • File upload handling
  • Approval workflow
  • DRF backend
  • React list, form, and admin views
Flow Design

Expense Workflow

stateDiagram-v2
    [*] --> Draft
    Draft --> Submitted
    Submitted --> Approved
    Submitted --> Rejected
    Rejected --> Submitted
    Approved --> Paid
Flow Design

Example Flow

flowchart TD
    Login[User logs in]
    Workspace[Selects workspace]
    Expenses[Opens Expense Tracker]

    Login --> Workspace --> Expenses

    Expenses --> Member[Member Flow]
    Expenses --> Admin[Admin Flow]
    Expenses --> Owner[Owner Flow]

    Member --> MemberList[View own expenses]
    MemberList --> MemberFilter[Search / filter / paginate own submissions]
    MemberFilter --> MemberCreate[Create expense draft]
    MemberCreate --> MemberUpload[Upload receipt securely]
    MemberUpload --> MemberSubmit[Submit expense for review]
    MemberSubmit --> MemberTrack[Track approval or rejection status]
    MemberTrack -. cannot approve own expense .-> MemberBlocked[Approval actions blocked]

    Admin --> AdminQueue[View workspace expense queue]
    AdminQueue --> AdminFilter[Search / filter / paginate by submitter, status, category]
    AdminFilter --> AdminView[Open expense detail and receipt preview]
    AdminView --> AdminDecision[Approve or reject with reason]
    AdminDecision -. cannot review other workspaces .-> AdminBlocked[Blocked by workspace permission rules]

    Owner --> OwnerOverview[View expenses across owned workspaces]
    OwnerOverview --> OwnerFilter[Filter by workspace, status, category, submitter]
    OwnerFilter --> OwnerView[Open expense detail]
    OwnerView --> OwnerManage[Approve, reject, audit, or confirm paid state]

Required Screens

My Expenses Page

Should show:

  • Expense title, amount, category, status, submitted date, and receipt indicator.
  • Search by title or category.
  • Filters for status, category, and date range.
  • Pagination if many submissions exist.
  • View button to open full expense details.
  • Receipt preview button for image and PDF files; all other file types should show download-only behavior.
  • Loading, empty, no-result, and error states.

Submit Expense Form

Fields:

  • Title, amount, category, date, description, and receipt upload.
  • File picker with allowed type and size validation for PDF, JPG, and PNG only.
  • Preview selected receipt before submit for PDF, JPG, and PNG files.
  • Replace/remove uploaded file before final save.
  • No direct public receipt URL; file access should stay private or signed.

Expense Detail / Receipt Preview

Should show:

  • Full expense summary with submitter, amounts, category, notes, and status history.
  • Receipt preview modal or drawer for supported formats.
  • Secure signed download action for the original file.
  • Decision metadata after approval or rejection.

Admin Expense Review Page

Should show:

  • Pending and reviewed expenses with submitter, amount, category, and status.
  • Search and filters for status, category, submitter, and date range.
  • Pagination for large review queues.
  • Receipt preview/download through signed or private access only.
  • Approve button and reject button.
  • Rejection reason field or modal that is required before reject completes.

Data Model

Recommended Expense fields:

FieldPurpose
workspaceWorkspace relation.
submitted_byUser who submitted expense.
titleExpense title.
amountExpense amount.
categoryTravel, food, office, etc.
receipt_fileUploaded receipt.
statusDraft, submitted, approved, rejected, paid.
reviewed_byAdmin/Owner who reviewed.
reviewed_atReview timestamp.
rejection_reasonRequired if rejected.

Permission Rules

ActorAllowed
OwnerView/manage all expenses in owned workspaces.
AdminReview expenses in assigned workspace.
MemberCreate/view own expenses.
Non-memberNo access.

Important rule:

A user should not approve their own expense.

File Upload Requirements

  • Validate file type.
  • Validate file size.
  • Store file securely.
  • Do not expose private files publicly.
  • Use signed/private download for all receipt access.

Allowed examples:

  • PDF
  • JPG
  • PNG

Blocked examples:

  • Executable files
  • Scripts
  • Unknown file types

Acceptance Checklist

  • Member can submit expense.
  • Receipt upload works.
  • Invalid files are blocked.
  • Admin can approve/reject workspace expenses.
  • Admin cannot see other workspace expenses.
  • User cannot approve own expense.
  • Rejection requires reason.
  • Status transitions are controlled server-side.
  • React handles loading, empty, and error states.