Version: 1.0.0
Last Updated: December 12, 2025
Law Firm: Neyra Marcos Mendez & Jungco Law Office
- System Overview
- System Requirements
- Installation Guide
- Configuration Guide
- User Guide
- Administrator Guide
- API Reference
- Database Schema
- Security & Authentication
- Troubleshooting
- Maintenance & Backup
- Development Guide
CaseVault is a comprehensive case management system specifically designed for law firms to efficiently manage clients, cases, hearings, and legal documentation. The system provides a modern, user-friendly interface with robust backend capabilities.
- Complete Client Profiles: Store comprehensive client information including personal details, contact information, and address
- Client Search: Real-time search functionality by name, email, phone, or client ID
- Client History: Track all cases associated with each client
- CRUD Operations: Full Create, Read, Update, Delete capabilities
- Data Validation: Automatic validation of email addresses and required fields
- Case Tracking: Monitor case status (Active, Pending, Closed)
- Case Types: Categorize cases by type (Contract Dispute, Personal Injury, etc.)
- Lawyer Assignment: Assign cases to specific lawyers
- Case Priority: Set priority levels (Low, Medium, High)
- Case Timeline: Track start and end dates
- Financial Tracking: Record estimated case values
- Case Descriptions: Detailed notes and descriptions for each case
- Real-time Statistics: View total clients, active cases, pending cases, and closed cases
- Quick Actions: Fast access to add clients and cases
- Search Functionality: Global search across clients and cases
- Status Filtering: Filter cases by status using tabs
- JWT-based Authentication: Secure token-based authentication system
- Email-based Login: Login using email addresses
- Session Management: Automatic token refresh and session handling
- Password Security: Secure password hashing and validation
- Protected Routes: Frontend and backend route protection
- CORS Security: Configured cross-origin resource sharing
- React 18.3.1: Modern JavaScript library for building user interfaces
- TypeScript: Type-safe JavaScript for better code quality
- Vite 6.4.1: Next-generation frontend build tool
- Tailwind CSS: Utility-first CSS framework
- Radix UI: Accessible component library
- React Router DOM 7.10.1: Client-side routing
- Lucide React: Icon library
- Sonner: Toast notification system
- React Hook Form: Form validation and management
- Django 4.2+: High-level Python web framework
- Django REST Framework: Powerful toolkit for building Web APIs
- djangorestframework-simplejwt: JWT authentication for Django REST Framework
- django-cors-headers: Handle Cross-Origin Resource Sharing
- Python 3.9+: Programming language
- psycopg2-binary: PostgreSQL adapter for Python
- PostgreSQL 12+: Advanced open-source relational database
- Structured Schema: Well-designed database with proper relationships
- Auto-timestamps: Automatic created_at and updated_at fields
- Foreign Key Constraints: Data integrity through relationships
- Git: Version control system
- npm: Package manager for JavaScript
- pip: Package manager for Python
- Virtual Environment: Isolated Python environment
┌─────────────────────────────────────────────────────────────┐
│ Client Browser │
│ (React + TypeScript) │
└────────────────────────┬────────────────────────────────────┘
│ HTTP/HTTPS
│ Port 5173 (Dev)
▼
┌─────────────────────────────────────────────────────────────┐
│ Frontend Server │
│ Vite Dev Server │
│ (http://localhost:5173) │
└────────────────────────┬────────────────────────────────────┘
│ REST API Calls
│ JWT Authentication
▼
┌─────────────────────────────────────────────────────────────┐
│ Backend Server │
│ Django REST Framework │
│ (http://localhost:8000) │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ API Endpoints │ │
│ │ - /api/token/ (Authentication) │ │
│ │ - /api/clients/ (Client Management) │ │
│ │ - /api/cases/ (Case Management) │ │
│ │ - /api/profile/ (User Profile) │ │
│ └──────────────────────────────────────────────────────┘ │
└────────────────────────┬────────────────────────────────────┘
│ SQL Queries
│ Port 5432
▼
┌─────────────────────────────────────────────────────────────┐
│ PostgreSQL Database │
│ (casevault_db) │
│ │
│ Tables: │
│ - clients (Client information) │
│ - cases (Case records) │
│ - users (User profiles) │
│ - hearings (Hearing schedules) │
│ - notifications (System notifications) │
│ - admin_logs (Audit trail) │
└─────────────────────────────────────────────────────────────┘
- Full system access
- User management
- System configuration
- Access to Django admin panel
- View audit logs
- Manage assigned cases
- View client information
- Update case status
- Add case notes
- Data entry
- Client management
- Basic case management
- Processor: Dual-core 2.0 GHz or higher
- RAM: 4 GB
- Storage: 10 GB available space
- Network: Stable internet connection
- Processor: Quad-core 2.5 GHz or higher
- RAM: 8 GB or more
- Storage: 20 GB SSD
- Network: High-speed internet connection
- Linux: Ubuntu 20.04 LTS or later (Recommended)
- macOS: 10.15 (Catalina) or later
- Windows: Windows 10 or later (with WSL2 for best experience)
Node.js
- Version: 16.x or higher
- Download: https://nodejs.org/
- Includes npm (Node Package Manager)
Python
- Version: 3.9 or higher
- Download: https://www.python.org/
- Includes pip (Python Package Manager)
PostgreSQL
- Version: 12 or higher
- Download: https://www.postgresql.org/
- Database server for data storage
Git
- Latest version
- Download: https://git-scm.com/
- Version control system
- Google Chrome: Version 90 or later (Recommended)
- Mozilla Firefox: Version 88 or later
- Microsoft Edge: Version 90 or later
- Safari: Version 14 or later
- JavaScript enabled
- Cookies enabled
- Local Storage support
- Modern CSS support (Flexbox, Grid)
- Ports:
- 5173: Frontend development server
- 8000: Backend API server
- 5432: PostgreSQL database
- Firewall: Allow connections on above ports
- Internet: Required for initial setup and package downloads
Before beginning installation, ensure you have:
- Administrator/sudo access to your system
- Stable internet connection
- All required software installed (Node.js, Python, PostgreSQL, Git)
- At least 10 GB free disk space
- Verified software versions using commands below
Open terminal and run these commands:
# Check Node.js version (should be 16.x or higher)
node --version
# Check npm version (should be 8.x or higher)
npm --version
# Check Python version (should be 3.9 or higher)
python3 --version
# Check PostgreSQL version (should be 12.x or higher)
psql --version
# Check Git version
git --version# Navigate to your projects directory
cd ~/projects
# Clone the repository
git clone https://github.com/yourusername/Marcos-CaseVault.git
# Navigate into the project directory
cd Marcos-CaseVault
# Verify the project structure
ls -laExpected output:
backend/
frontend/
setup_postgres.sh
README.md
.gitignore
# Make the setup script executable
chmod +x setup_postgres.sh
# Run the setup script
./setup_postgres.shThe script will:
- Install PostgreSQL (if not already installed)
- Start PostgreSQL service
- Create database:
casevault_db - Create user:
casevault_user - Set password:
casevault_pass123 - Grant necessary privileges
- Grant schema permissions
Expected output:
Setting up PostgreSQL for CaseVault...
PostgreSQL setup complete!
Database: casevault_db
User: casevault_user
Password: casevault_pass123
If you prefer manual setup or the script fails:
# Install PostgreSQL (Ubuntu/Debian)
sudo apt update
sudo apt install postgresql postgresql-contrib
# Start PostgreSQL service
sudo systemctl start postgresql
sudo systemctl enable postgresql
# Access PostgreSQL as postgres user
sudo -u postgres psqlIn the PostgreSQL shell, run:
-- Create database
CREATE DATABASE casevault_db;
-- Create user with password
CREATE USER casevault_user WITH PASSWORD 'casevault_pass123';
-- Grant privileges
GRANT ALL PRIVILEGES ON DATABASE casevault_db TO casevault_user;
-- Allow user to create databases (for testing)
ALTER USER casevault_user CREATEDB;
-- Exit PostgreSQL shell
\qGrant schema permissions:
# Grant schema permissions
sudo -u postgres psql -d casevault_db -c "GRANT ALL ON SCHEMA public TO casevault_user;"# Test database connection
psql -U casevault_user -d casevault_db -h localhost
# If successful, you'll see:
# casevault_db=>
# Exit with:
\qcd backend# Create virtual environment
python3 -m venv .venv
# Activate virtual environment
# On Linux/macOS:
source .venv/bin/activate
# On Windows:
.venv\Scripts\activate
# Your prompt should now show (.venv)# Upgrade pip
pip install --upgrade pip
# Install required packages
pip install -r requirements.txtDependencies installed:
- Django>=4.2.0
- djangorestframework
- djangorestframework-simplejwt
- django-cors-headers
- psycopg2-binary
- boto3
# Create database tables
python manage.py migrateExpected output:
Operations to perform:
Apply all migrations: admin, auth, contenttypes, core, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
...
Applying core.0001_initial... OK
Applying sessions.0001_initial... OK
# Run the superuser creation script
python create_superuser.pyExpected output:
Superuser created: admin@nmmlaw.com / admin123
Test user created: test@example.com / testpass123
# Start Django development server
python manage.py runserver 8000Expected output:
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
December 12, 2025 - 09:00:00
Django version 4.2.0, using settings 'casevault.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
# Make start script executable
chmod +x start.sh
# Run start script (does all backend setup)
./start.shThe start.sh script will:
- Activate virtual environment
- Install dependencies
- Run migrations
- Create superuser
- Start server
Open a new terminal window (keep backend running).
cd frontend# Install all npm packages
npm installThis will install all dependencies listed in package.json (may take 2-5 minutes).
Create a .env file in the frontend directory:
# Create .env file
touch .env
# Add configuration
echo "VITE_API_BASE_URL=http://localhost:8000/api" > .envOr manually create .env with this content:
VITE_API_BASE_URL=http://localhost:8000/api# Start Vite development server
npm run devExpected output:
VITE v6.4.1 ready in 500 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
Open your web browser and navigate to:
Frontend Application
- URL: http://localhost:5173
- Login with: admin@nmmlaw.com / admin123
Backend API
- URL: http://localhost:8000/api
- API Documentation: http://localhost:8000/api/
Django Admin Panel
- URL: http://localhost:8000/admin
- Login with: admin@nmmlaw.com / admin123
- Open http://localhost:5173
- You should see the login page
- Login with admin@nmmlaw.com / admin123
- You should be redirected to the dashboard
# Test health endpoint
curl http://localhost:8000/api/health/
# Expected response:
# {"status":"healthy"}# Access Django shell
python manage.py shell
# In the shell:
from core.models import Client
print(Client.objects.count())
# Should print: 0
# Exit shell
exit()Database Configuration
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'casevault_db',
'USER': 'casevault_user',
'PASSWORD': 'casevault_pass123',
'HOST': 'localhost',
'PORT': '5432',
}
}CORS Settings
CORS_ALLOWED_ORIGINS = [
"http://localhost:5173", # Vite dev server
"http://127.0.0.1:5173",
"http://localhost:3000", # Alternative port
"http://127.0.0.1:3000",
]
CORS_ALLOW_CREDENTIALS = TrueJWT Token Settings
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': True,
}Security Settings
SECRET_KEY = 'your-secret-key-here' # Change in production
DEBUG = True # Set to False in production
ALLOWED_HOSTS = ['localhost', '127.0.0.1'] # Add domain in productionCreate .env file in backend directory (optional):
DATABASE_NAME=casevault_db
DATABASE_USER=casevault_user
DATABASE_PASSWORD=casevault_pass123
DATABASE_HOST=localhost
DATABASE_PORT=5432
SECRET_KEY=your-secret-key
DEBUG=True# API Base URL
VITE_API_BASE_URL=http://localhost:8000/api
# Optional: API Timeout (milliseconds)
VITE_API_TIMEOUT=30000
# Optional: Enable Debug Mode
VITE_DEBUG=trueimport { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import path from 'path'
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
server: {
port: 5173,
host: true,
},
})The system is pre-configured with four lawyers from Neyra Marcos Mendez & Jungco Law Office:
- Atty. Prince Arthur M. Neyra
- Atty. Cloydie Mark A. Marcos
- Atty. Ryan E. Mendez
- Atty. Deolanar C. Jungco
To modify lawyers, edit:
frontend/src/components/Dashboard.tsx(line 614-618)frontend/src/components/AddClientPage.tsx(line 54-58)
Default case types:
- Contract Dispute
- Personal Injury
- Family Law
- Criminal Defense
- Real Estate
- Employment Law
- Intellectual Property
- Corporate Law
To modify, edit the caseTypes array in:
frontend/src/components/Dashboard.tsxfrontend/src/components/AddClientPage.tsx
- Open your browser and navigate to http://localhost:5173
- You will see the login page
- Enter credentials:
- Email: admin@nmmlaw.com
- Password: admin123
- Click "Sign In"
- You will be redirected to the Dashboard
Sidebar Navigation
- Dashboard: Main overview page
- Clients: View all clients
- Cases: View all cases
- Add Client: Quick access to add new client
- Lawyers: View lawyer information
- About: System information
Top Bar
- Search functionality
- User profile menu
- Logout button
Method 1: From Dashboard
- Click "Add Client" button on dashboard
- Fill in the client information form
Method 2: From Add Client Page
- Click "Add Client" in sidebar
- Fill in the comprehensive form
Required Fields:
- First Name
- Last Name
Optional Fields:
- Middle Name
- Date of Birth
- Civil Status
- Phone Number
- Address (Street, City, State, ZIP Code)
- Opposing Parties
- Notes
Adding Cases to New Client:
-
Scroll to "Case Information" section
-
Click "Add Another Case" to add multiple cases
-
For each case, fill in:
- Lawyer Assigned (required) - Select from dropdown
- Case Title (required)
- Case Type (required) - Select from dropdown
- Status (required) - Active, Pending, or Closed
- Description (optional)
-
Click "Add Client with Cases" to save
Form Validation:
- Email must be valid format
- All required fields must be filled
- Duplicate emails are not allowed
From Dashboard:
- All clients are displayed as cards
- Each card shows:
- Client ID
- Full name
- Phone number
- Number of cases
- Action buttons (Edit, Delete, Add Case)
Search Functionality:
- Use the search bar at the top
- Search by:
- Client name
- Phone number
- Client ID
- Results update in real-time
- Find the client on the dashboard
- Click the Edit button (pencil icon)
- A modal will appear with the client's current information
- Modify the fields you want to change
- Click "Update Client" to save changes
- Click "Cancel" to discard changes
Editable Fields:
- All client information fields
- Cannot change Client ID (auto-generated)
- Find the client on the dashboard
- Click the Delete button (trash icon)
- A confirmation dialog will appear
- Click "Delete" to confirm
- Click "Cancel" to abort
Warning: Deleting a client will also delete all associated cases. This action cannot be undone.
From Dashboard:
- Find the client card
- Click the "+" button next to "Cases: X"
- Fill in the case form:
- Case Title (required)
- Case Type (required) - Select from dropdown
- Status (required) - Active/Pending/Closed
- Lawyer Assigned (required) - Select from dropdown
- Description (optional)
- Click "Add Case"
From Cases Page:
- Navigate to "Cases" in sidebar
- Click "Add Case" button
- Select client from dropdown
- Fill in case details
- Click "Save Case"
- Click "Cases" in the sidebar
- All cases are displayed as cards
- Each card shows:
- Case ID
- Client name
- Case title
- Case type
- Status badge
- Lawyer assigned
- Description
- Created date
Filtering by Status:
- Use tabs at the top:
- All: Show all cases
- Active: Show only active cases
- Pending: Show only pending cases
- Closed: Show only closed cases
Search Functionality:
- Search by:
- Client name
- Case ID
- Case title
- Case type
- Lawyer name
- Results update in real-time
- Go to Cases page
- Find the case you want to edit
- Click the Edit button on the case card
- Modify the case information in the modal
- Click "Update Case" to save
- Click "Cancel" to discard changes
Editable Fields:
- Case title
- Case type
- Status
- Lawyer assigned
- Description
- Go to Cases page
- Find the case you want to delete
- Click the Delete button
- Confirm deletion in the dialog
- The case will be permanently removed
Note: Deleting a case does not delete the associated client.
The dashboard displays four key metrics:
-
Total Clients
- Count of all clients in the system
- Blue card with Users icon
-
Active Cases
- Count of cases with "Active" status
- Green card with Briefcase icon
-
Pending Cases
- Count of cases with "Pending" status
- Yellow card with Clock icon
-
Closed Cases
- Count of cases with "Closed" status
- Gray card with CheckCircle icon
Add Client Button
- Located at top right of dashboard
- Opens Add Client page
- Quick access to create new client profiles
Add Case Button
- Located on each client card
- Opens case creation modal
- Pre-fills client information
Each client card displays:
- Client ID: Unique identifier
- Full Name: First, middle, and last name
- Email: Contact email address
- Phone: Contact phone number
- Case Count: Number of associated cases
- Action Buttons:
- Edit (pencil icon)
- Delete (trash icon)
- Add Case (+ button)
Dashboard Search:
- Located at top of page
- Searches across all clients
- Real-time results
- Search criteria:
- First name
- Last name
- Phone number
- Client ID
Cases Page Search:
- Located at top of Cases page
- Searches across all cases
- Real-time results
- Search criteria:
- Client name
- Case ID
- Case title
- Case type
- Lawyer assigned
Cases Page Tabs:
- All: Display all cases regardless of status
- Active: Filter to show only active cases
- Pending: Filter to show only pending cases
- Closed: Filter to show only closed cases
Combining Search and Filters:
- Use tabs to filter by status
- Use search to further narrow results
- Both work together for precise filtering
- Click on user icon in top right
- Select "Profile" from dropdown
- View your account information
Method 1: Django Admin
- Navigate to http://localhost:8000/admin
- Login with admin credentials
- Click "Users" in the sidebar
- Select your user account
- Click "Change password"
- Enter new password twice
- Click "Save"
Method 2: Forgot Password (if enabled)
- Click "Forgot Password" on login page
- Enter your email
- Follow reset instructions
- Click user icon in top right
- Select "Logout" from dropdown
- You will be redirected to login page
- Your session will be terminated
Security Note: Always logout when using shared computers.
- Navigate to http://localhost:8000/admin
- Login with admin credentials:
- Email: admin@nmmlaw.com
- Password: admin123
Dashboard:
- Overview of all database tables
- Quick access to manage records
- Recent actions log
Available Sections:
- Authentication and Authorization
- Users
- Groups
- Core
- Clients
- Cases
- User Profiles
- Hearings
- Notifications
- Admin Logs
- Go to Django Admin Panel
- Click "Users" under Authentication
- Click "Add User" button
- Fill in required information:
- Username (use email format)
- Password
- Password confirmation
- Click "Save and continue editing"
- Fill in additional details:
- First name
- Last name
- Email address
- Staff status
- Superuser status
- Click "Save"
Superuser:
- Full access to all features
- Can access Django admin
- Can manage other users
- Can view audit logs
Staff:
- Can access Django admin
- Limited permissions based on groups
- Cannot manage users
Regular User:
- Cannot access Django admin
- Can only use frontend application
- Limited to assigned cases
- Go to Django Admin Panel
- Click "User Profiles" under Core
- Select user profile
- Set role:
- Lawyer
- Admin
- Staff
- Click "Save"
- Go to Users section
- Select user
- Uncheck "Active" checkbox
- Click "Save"
Note: Deactivated users cannot login but their data is preserved.
Clients:
- Go to "Clients" in Core section
- View list of all clients
- Click on client to view/edit details
- Use filters on right sidebar
- Use search box to find specific clients
Cases:
- Go to "Cases" in Core section
- View list of all cases
- Filter by status, priority, lawyer
- Click on case to view/edit details
Hearings:
- Go to "Hearings" in Core section
- View scheduled hearings
- Filter by status, date
- Edit hearing details
Bulk Delete:
- Select multiple records using checkboxes
- Choose "Delete selected" from Actions dropdown
- Click "Go"
- Confirm deletion
Bulk Update:
- Select multiple records
- Choose appropriate action from dropdown
- Click "Go"
- Confirm changes
Method 1: Django Admin
- Install django-import-export (optional)
- Use export functionality in admin
Method 2: Database Dump
# Export entire database
pg_dump -U casevault_user -h localhost casevault_db > backup.sql
# Export specific table
pg_dump -U casevault_user -h localhost -t clients casevault_db > clients_backup.sqlDjango Logs:
- Located in backend directory
- Check console output for errors
- Review
django.logif configured
Admin Logs:
- Go to Django Admin Panel
- Click "Admin Logs" under Core
- View all system actions:
- User actions
- Record changes
- IP addresses
- Timestamps
Database Queries:
# Connect to database
psql -U casevault_user -d casevault_db
# View active connections
SELECT * FROM pg_stat_activity;
# View table sizes
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;Server Status:
# Check Django server status
ps aux | grep manage.py
# Check PostgreSQL status
sudo systemctl status postgresql
# Check disk usage
df -hChanging User Passwords:
- Go to Django Admin
- Select user
- Click "Change password"
- Enter new password
- Confirm and save
Password Requirements:
- Minimum 8 characters
- Cannot be too similar to username
- Cannot be entirely numeric
- Cannot be too common
JWT Token Settings:
- Access token lifetime: 60 minutes
- Refresh token lifetime: 7 days
- Tokens automatically rotate on refresh
Force Logout All Users:
# Clear all sessions
python manage.py clearsessionsViewing Audit Logs:
- Go to Admin Logs in Django Admin
- Filter by:
- User
- Action type
- Date range
- Table name
- Export logs for compliance
Log Information Includes:
- User ID
- Action performed
- Table affected
- Record ID
- Old values
- New values
- IP address
- User agent
- Timestamp
Description: Obtain JWT access and refresh tokens
Request:
{
"username": "admin@nmmlaw.com",
"password": "admin123"
}Response (200 OK):
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}Error Responses:
- 401 Unauthorized: Invalid credentials
- 400 Bad Request: Missing required fields
Description: Refresh access token using refresh token
Request:
{
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}Response (200 OK):
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}Description: Retrieve all clients
Headers:
Authorization: Bearer <access_token>
Response (200 OK):
[
{
"client_id": 1,
"first_name": "John",
"middle_name": "Michael",
"last_name": "Doe",
"date_of_birth": "1985-05-15",
"civil_status": "Married",
"phone_number": "123-456-7890",
"email": "john.doe@example.com",
"street": "123 Main St",
"city": "Manila",
"state": "Metro Manila",
"zip_code": "1000",
"opposing_parties": "ABC Corporation",
"notes": "Important client",
"created_at": "2025-12-12T09:00:00Z",
"updated_at": "2025-12-12T09:00:00Z"
}
]Description: Create a new client
Headers:
Authorization: Bearer <access_token>
Content-Type: application/json
Request:
{
"first_name": "Jane",
"last_name": "Smith",
"email": "jane.smith@example.com",
"phone_number": "098-765-4321",
"street": "456 Oak Ave",
"city": "Quezon City",
"state": "Metro Manila",
"zip_code": "1100"
}Response (201 Created):
{
"client_id": 2,
"first_name": "Jane",
"last_name": "Smith",
"email": "jane.smith@example.com",
...
}Description: Retrieve specific client
Headers:
Authorization: Bearer <access_token>
Response (200 OK):
{
"client_id": 1,
"first_name": "John",
"last_name": "Doe",
...
}Description: Update client information
Headers:
Authorization: Bearer <access_token>
Content-Type: application/json
Request:
{
"first_name": "John Updated",
"phone_number": "111-222-3333"
}Response (200 OK):
{
"client_id": 1,
"first_name": "John Updated",
"phone_number": "111-222-3333",
...
}Description: Delete a client and all associated cases
Headers:
Authorization: Bearer <access_token>
Response (204 No Content)
Description: Retrieve all cases
Headers:
Authorization: Bearer <access_token>
Query Parameters:
status: Filter by status (active, pending, closed)client_id: Filter by client IDlawyer_assigned: Filter by lawyer name
Response (200 OK):
[
{
"case_id": 1,
"client_id": 1,
"case_title": "Contract Dispute Case",
"case_type": "Contract Dispute",
"status": "active",
"description": "Dispute over contract terms",
"priority": "high",
"estimated_value": "500000.00",
"start_date": "2025-01-01",
"end_date": null,
"lawyer_assigned": "Atty. Prince Arthur M. Neyra",
"created_at": "2025-12-12T09:00:00Z",
"updated_at": "2025-12-12T09:00:00Z"
}
]Description: Create a new case
Headers:
Authorization: Bearer <access_token>
Content-Type: application/json
Request:
{
"client_id": 1,
"case_title": "Personal Injury Case",
"case_type": "Personal Injury",
"status": "active",
"description": "Car accident case",
"lawyer_assigned": "Atty. Cloydie Mark A. Marcos",
"priority": "high"
}Response (201 Created):
{
"case_id": 2,
"client_id": 1,
"case_title": "Personal Injury Case",
...
}Description: Update case information
Headers:
Authorization: Bearer <access_token>
Content-Type: application/json
Request:
{
"status": "closed",
"description": "Case resolved successfully"
}Response (200 OK):
{
"case_id": 1,
"status": "closed",
"description": "Case resolved successfully",
...
}Description: Delete a case
Headers:
Authorization: Bearer <access_token>
Response (204 No Content)
Description: Get current user profile
Headers:
Authorization: Bearer <access_token>
Response (200 OK):
{
"user_id": 1,
"email": "admin@nmmlaw.com",
"first_name": "Admin",
"last_name": "User",
"role": "admin",
"phone_number": "123-456-7890",
"is_active": true
}400 Bad Request:
{
"error": "Invalid request data",
"details": {
"email": ["This field is required"]
}
}401 Unauthorized:
{
"detail": "Authentication credentials were not provided."
}403 Forbidden:
{
"detail": "You do not have permission to perform this action."
}404 Not Found:
{
"detail": "Not found."
}500 Internal Server Error:
{
"error": "Internal server error",
"message": "An unexpected error occurred"
}The CaseVault database consists of 6 main tables:
- clients - Client information
- cases - Case records
- users - User profiles
- hearings - Hearing schedules
- notifications - System notifications
- admin_logs - Audit trail
Table Name: clients
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| client_id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique client identifier |
| first_name | VARCHAR(100) | NOT NULL | Client's first name |
| middle_name | VARCHAR(100) | NULL | Client's middle name |
| last_name | VARCHAR(100) | NOT NULL | Client's last name |
| date_of_birth | DATE | NULL | Client's date of birth |
| civil_status | VARCHAR(50) | NULL | Marital status |
| phone_number | VARCHAR(20) | NULL | Contact phone number |
| VARCHAR(254) | UNIQUE, NULL | Email address | |
| street | VARCHAR(255) | NULL | Street address |
| city | VARCHAR(100) | NULL | City |
| state | VARCHAR(100) | NULL | State/Province |
| zip_code | VARCHAR(20) | NULL | Postal code |
| opposing_parties | TEXT | NULL | Opposing party information |
| notes | TEXT | NULL | Additional notes |
| created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | Record creation timestamp |
| updated_at | TIMESTAMP | NOT NULL, AUTO_UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY on
client_id - UNIQUE INDEX on
email - INDEX on
last_name,first_namefor search optimization
Table Name: cases
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| case_id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique case identifier |
| client_id | INTEGER | FOREIGN KEY (clients.client_id), NOT NULL | Reference to client |
| case_title | VARCHAR(255) | NOT NULL | Case title |
| case_type | VARCHAR(100) | NULL | Type of case |
| status | VARCHAR(50) | NOT NULL, DEFAULT 'active' | Case status (active/pending/closed) |
| description | TEXT | NULL | Case description |
| priority | VARCHAR(20) | DEFAULT 'medium' | Priority level (low/medium/high) |
| estimated_value | DECIMAL(15,2) | NULL | Estimated case value |
| start_date | DATE | NULL | Case start date |
| end_date | DATE | NULL | Case end date |
| lawyer_assigned | VARCHAR(255) | NULL | Assigned lawyer name |
| created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | Record creation timestamp |
| updated_at | TIMESTAMP | NOT NULL, AUTO_UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY on
case_id - FOREIGN KEY on
client_idREFERENCESclients(client_id)ON DELETE CASCADE - INDEX on
statusfor filtering - INDEX on
lawyer_assignedfor filtering
Relationships:
- Many-to-One with
clients(one client can have many cases) - CASCADE DELETE: Deleting a client deletes all associated cases
Table Name: users
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| user_id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique user identifier |
| django_user_id | INTEGER | FOREIGN KEY, UNIQUE | Reference to Django auth_user |
| cognito_user_id | VARCHAR(255) | UNIQUE, NULL | AWS Cognito user ID |
| role | VARCHAR(50) | DEFAULT 'lawyer' | User role (lawyer/admin/staff) |
| phone_number | VARCHAR(20) | NULL | Contact phone number |
| is_active | BOOLEAN | DEFAULT TRUE | Account active status |
| created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | Record creation timestamp |
| updated_at | TIMESTAMP | NOT NULL, AUTO_UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY on
user_id - UNIQUE INDEX on
django_user_id - UNIQUE INDEX on
cognito_user_id
Table Name: hearings
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| hearing_id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique hearing identifier |
| case_id | INTEGER | FOREIGN KEY (cases.case_id), NOT NULL | Reference to case |
| hearing_date | TIMESTAMP | NOT NULL | Scheduled hearing date/time |
| hearing_type | VARCHAR(100) | NULL | Type of hearing |
| location | VARCHAR(255) | NULL | Hearing location |
| judge_name | VARCHAR(255) | NULL | Presiding judge name |
| notes | TEXT | NULL | Hearing notes |
| status | VARCHAR(50) | DEFAULT 'scheduled' | Status (scheduled/completed/cancelled/postponed) |
| created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | Record creation timestamp |
| updated_at | TIMESTAMP | NOT NULL, AUTO_UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY on
hearing_id - FOREIGN KEY on
case_idREFERENCEScases(case_id)ON DELETE CASCADE - INDEX on
hearing_datefor scheduling queries - INDEX on
statusfor filtering
Table Name: notifications
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| notification_id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique notification identifier |
| user_id | INTEGER | FOREIGN KEY (users.user_id), NOT NULL | Reference to user |
| title | VARCHAR(255) | NOT NULL | Notification title |
| message | TEXT | NULL | Notification message |
| type | VARCHAR(50) | DEFAULT 'info' | Type (info/warning/error/success) |
| is_read | BOOLEAN | DEFAULT FALSE | Read status |
| created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | Creation timestamp |
Indexes:
- PRIMARY KEY on
notification_id - FOREIGN KEY on
user_idREFERENCESusers(user_id)ON DELETE CASCADE - INDEX on
user_id,is_readfor filtering unread notifications
Table Name: admin_logs
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| log_id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique log identifier |
| user_id | VARCHAR(255) | NULL | User who performed action |
| action | VARCHAR(100) | NOT NULL | Action performed |
| table_name | VARCHAR(100) | NULL | Affected table |
| record_id | VARCHAR(100) | NULL | Affected record ID |
| old_values | JSON | NULL | Previous values |
| new_values | JSON | NULL | New values |
| ip_address | INET | NULL | User's IP address |
| user_agent | TEXT | NULL | User's browser/client info |
| created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | Action timestamp |
Indexes:
- PRIMARY KEY on
log_id - INDEX on
user_idfor user activity tracking - INDEX on
created_atfor time-based queries - INDEX on
table_name,record_idfor record history
┌─────────────────┐
│ CLIENTS │
│─────────────────│
│ client_id (PK) │
│ first_name │
│ last_name │
│ email (UNIQUE) │
│ phone_number │
│ ... │
└────────┬────────┘
│
│ 1:N
│
┌────────▼────────┐
│ CASES │
│─────────────────│
│ case_id (PK) │
│ client_id (FK) │
│ case_title │
│ status │
│ lawyer_assigned │
│ ... │
└────────┬────────┘
│
│ 1:N
│
┌────────▼────────┐
│ HEARINGS │
│─────────────────│
│ hearing_id (PK) │
│ case_id (FK) │
│ hearing_date │
│ status │
│ ... │
└─────────────────┘
┌─────────────────┐
│ AUTH_USER │
│ (Django) │
│─────────────────│
│ id (PK) │
│ username │
│ email │
│ password │
└────────┬────────┘
│
│ 1:1
│
┌────────▼────────┐
│ USERS │
│─────────────────│
│ user_id (PK) │
│ django_user_id │
│ role │
│ ... │
└────────┬────────┘
│
│ 1:N
│
┌────────▼────────┐
│ NOTIFICATIONS │
│─────────────────│
│ notification_id │
│ user_id (FK) │
│ title │
│ is_read │
└─────────────────┘
-
User Login:
- User submits email and password
- Backend validates credentials
- Returns access token (60 min) and refresh token (7 days)
-
API Requests:
- Frontend includes access token in Authorization header
- Backend validates token on each request
- Returns requested data if valid
-
Token Refresh:
- When access token expires, use refresh token
- Backend issues new access token
- Refresh token rotates for security
-
Logout:
- Frontend discards tokens
- User must re-authenticate
- Uses Django's PBKDF2 algorithm
- Salted hashes stored in database
- Passwords never stored in plain text
- Minimum 8 characters
- Cannot be too similar to username
- Cannot be entirely numeric
- Cannot be common passwords
- Secure token-based reset flow
- Tokens expire after 24 hours
- Email verification required
CORS_ALLOWED_ORIGINS = [
"http://localhost:5173",
"http://127.0.0.1:5173",
]
CORS_ALLOW_CREDENTIALS = True- All API endpoints require JWT token
- Except: /api/token/ (login)
- Token must be in Authorization header
- Implement rate limiting in production
- Prevent brute force attacks
- Use Django middleware or nginx
- All user inputs validated
- SQL injection prevention
- XSS attack prevention
- Always use HTTPS in production
- Encrypt data in transit
- Use valid SSL certificates
- Strong database passwords
- Limited database user permissions
- Regular security updates
django.db.utils.OperationalError: could not connect to server
Solutions:
-
Check PostgreSQL is running:
sudo systemctl status postgresql sudo systemctl start postgresql
-
Verify database credentials in
settings.py -
Test database connection:
psql -U casevault_user -d casevault_db -h localhost
-
Check PostgreSQL logs:
sudo tail -f /var/log/postgresql/postgresql-*.log
permission denied for schema public
Solution:
sudo -u postgres psql -d casevault_db -c "GRANT ALL ON SCHEMA public TO casevault_user;"Access to fetch blocked by CORS policy
Solutions:
- Verify Django server is running on port 8000
- Check CORS settings in
settings.py:CORS_ALLOWED_ORIGINS = [ "http://localhost:5173", ]
- Clear browser cache
- Check browser console for exact error
Module not found: Can't resolve './components/...'
Solutions:
- Check file paths and imports
- Reinstall dependencies:
rm -rf node_modules package-lock.json npm install
- Clear Vite cache:
rm -rf node_modules/.vite
401 Unauthorized
Solutions:
- Check if token is expired
- Verify token is in Authorization header
- Check user credentials
- Clear browser localStorage:
localStorage.clear()
Error: listen EADDRINUSE: address already in use :::5173
Solutions:
- Find process using port:
lsof -i :5173
- Kill the process:
kill -9 <PID>
- Or use different port:
npm run dev -- --port 3000
Enable Debug Mode:
# settings.py
DEBUG = TrueView Django Logs:
# In terminal running Django server
# All requests and errors are loggedDjango Shell:
python manage.py shell
# Test database queries
from core.models import Client
Client.objects.all()Database Queries:
# Connect to database
psql -U casevault_user -d casevault_db
# View all clients
SELECT * FROM clients;
# View all cases
SELECT * FROM cases;Browser Console:
- Open Developer Tools (F12)
- Check Console tab for errors
- Check Network tab for API calls
React DevTools:
- Install React Developer Tools extension
- Inspect component state and props
Check API Responses:
// In browser console
fetch('http://localhost:8000/api/clients/', {
headers: {
'Authorization': 'Bearer ' + localStorage.getItem('access_token')
}
}).then(r => r.json()).then(console.log)Add Indexes:
CREATE INDEX idx_clients_email ON clients(email);
CREATE INDEX idx_cases_status ON cases(status);Analyze Queries:
EXPLAIN ANALYZE SELECT * FROM cases WHERE status = 'active';Solutions:
- Enable production build:
npm run build npm run preview
- Optimize images
- Implement lazy loading
- Use React.memo for expensive components
Full Database Backup:
# Backup entire database
pg_dump -U casevault_user -h localhost casevault_db > backup_$(date +%Y%m%d).sql
# Backup with compression
pg_dump -U casevault_user -h localhost casevault_db | gzip > backup_$(date +%Y%m%d).sql.gzTable-Specific Backup:
# Backup clients table only
pg_dump -U casevault_user -h localhost -t clients casevault_db > clients_backup.sql
# Backup cases table only
pg_dump -U casevault_user -h localhost -t cases casevault_db > cases_backup.sqlCreate backup.sh:
#!/bin/bash
BACKUP_DIR="/home/backups/casevault"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
pg_dump -U casevault_user -h localhost casevault_db | gzip > $BACKUP_DIR/backup_$DATE.sql.gz
# Keep only last 30 days of backups
find $BACKUP_DIR -name "backup_*.sql.gz" -mtime +30 -delete
echo "Backup completed: backup_$DATE.sql.gz"Schedule with Cron:
# Edit crontab
crontab -e
# Add daily backup at 2 AM
0 2 * * * /path/to/backup.shRestore Full Database:
# Drop existing database (WARNING: This deletes all data)
dropdb -U casevault_user casevault_db
# Create new database
createdb -U casevault_user casevault_db
# Restore from backup
psql -U casevault_user -d casevault_db < backup_20251212.sql
# Or from compressed backup
gunzip -c backup_20251212.sql.gz | psql -U casevault_user -d casevault_dbRestore Specific Table:
# Restore only clients table
psql -U casevault_user -d casevault_db < clients_backup.sqlcd backend
source .venv/bin/activate
# Update all packages
pip install --upgrade pip
pip install --upgrade -r requirements.txt
# Update requirements.txt
pip freeze > requirements.txt
# Run migrations
python manage.py migratecd frontend
# Check for outdated packages
npm outdated
# Update all packages
npm update
# Update specific package
npm install package-name@latest
# Update package.json
npm install# Connect to database
psql -U casevault_user -d casevault_db
# Vacuum all tables
VACUUM ANALYZE;
# Vacuum specific table
VACUUM ANALYZE clients;-- Total database size
SELECT pg_size_pretty(pg_database_size('casevault_db'));
-- Table sizes
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;-- Reindex all tables
REINDEX DATABASE casevault_db;
-- Reindex specific table
REINDEX TABLE clients;Configure Logging in settings.py:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'INFO',
'class': 'logging.FileHandler',
'filename': 'django.log',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'INFO',
'propagate': True,
},
},
}Rotate Logs:
# Install logrotate
sudo apt install logrotate
# Create logrotate config
sudo nano /etc/logrotate.d/casevault
# Add configuration:
/path/to/backend/django.log {
daily
rotate 30
compress
delaycompress
notifempty
create 0640 www-data www-data
}View Logs:
sudo tail -f /var/log/postgresql/postgresql-*.logConfigure Log Rotation:
# Edit PostgreSQL config
sudo nano /etc/postgresql/*/main/postgresql.conf
# Set log rotation
log_rotation_age = 1d
log_rotation_size = 100MB- Node.js 16+
- Python 3.9+
- PostgreSQL 12+
- Git
- Code editor (VS Code recommended)
- Python
- Pylance
- ESLint
- Prettier
- Tailwind CSS IntelliSense
- GitLens
backend/
├── casevault/ # Django project settings
│ ├── settings.py # Configuration
│ ├── urls.py # URL routing
│ └── wsgi.py # WSGI config
├── api/ # API endpoints
│ ├── views.py # API views
│ ├── serializers.py # Data serializers
│ └── urls.py # API URLs
├── core/ # Core models
│ ├── models.py # Database models
│ └── admin.py # Admin config
└── manage.py # Django CLI
frontend/
├── src/
│ ├── components/ # React components
│ │ ├── ui/ # Reusable UI components
│ │ ├── Dashboard.tsx
│ │ ├── CasesPage.tsx
│ │ └── LoginPage.tsx
│ ├── services/ # API services
│ │ ├── api-service.tsx
│ │ └── auth-service.tsx
│ └── App.tsx # Main app
├── public/ # Static assets
└── package.json # Dependencies
- Create Serializer (
api/serializers.py):
class NewFeatureSerializer(serializers.ModelSerializer):
class Meta:
model = NewFeature
fields = '__all__'- Create View (
api/views.py):
class NewFeatureViewSet(viewsets.ModelViewSet):
queryset = NewFeature.objects.all()
serializer_class = NewFeatureSerializer
permission_classes = [IsAuthenticated]- Add URL (
api/urls.py):
router.register(r'newfeature', NewFeatureViewSet)- Create Component (
src/components/NewFeature.tsx):
export function NewFeature() {
return (
<div>
<h1>New Feature</h1>
</div>
)
}- Add Route (
src/App.tsx):
<Route path="/newfeature" element={<NewFeature />} />- Add Navigation (Sidebar):
<Link to="/newfeature">New Feature</Link>Create Test File (api/tests.py):
from django.test import TestCase
from core.models import Client
class ClientTestCase(TestCase):
def setUp(self):
Client.objects.create(
first_name="John",
last_name="Doe",
email="john@example.com"
)
def test_client_creation(self):
client = Client.objects.get(email="john@example.com")
self.assertEqual(client.first_name, "John")Run Tests:
python manage.py testInstall Testing Libraries:
npm install --save-dev @testing-library/react @testing-library/jest-domCreate Test File (src/components/NewFeature.test.tsx):
import { render, screen } from '@testing-library/react'
import { NewFeature } from './NewFeature'
test('renders new feature', () => {
render(<NewFeature />)
const element = screen.getByText(/New Feature/i)
expect(element).toBeInTheDocument()
})Run Tests:
npm test# Create feature branch
git checkout -b feature/new-feature
# Make changes and commit
git add .
git commit -m "Add: new feature description"
# Push to remote
git push origin feature/new-feature
# Create pull request on GitHubType: Brief description
Detailed description if needed
Types:
- Add: New feature
- Fix: Bug fix
- Update: Update existing feature
- Remove: Remove feature
- Refactor: Code refactoring
- Docs: Documentation changes
- Set DEBUG = False
- Configure ALLOWED_HOSTS
- Use environment variables for secrets
- Enable HTTPS
- Configure static files
- Set up database backups
- Configure logging
- Set up monitoring
- Test all features
- Update documentation
Backend (.env):
DEBUG=False
SECRET_KEY=your-production-secret-key
DATABASE_URL=postgresql://user:pass@host:port/dbname
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.comFrontend (.env.production):
VITE_API_BASE_URL=https://api.yourdomain.com/apiDocumentation:
- Read this manual thoroughly
- Check README.md for quick start
- Review API documentation
Common Issues:
- Check Troubleshooting section
- Search GitHub issues
- Review error logs
Community Support:
- Create GitHub issue
- Include error messages
- Provide steps to reproduce
When reporting bugs, include:
- Description of the issue
- Steps to reproduce
- Expected behavior
- Actual behavior
- Error messages/logs
- System information
- Screenshots if applicable
To request new features:
- Check if feature already exists
- Search existing feature requests
- Create detailed feature request
- Explain use case
- Provide examples
Browser:
Ctrl + KorCmd + K: Focus searchEsc: Close modalsTab: Navigate form fields
Development:
Ctrl + C: Stop serverCtrl + Z: UndoCtrl + Shift + F: Format code
Admin Account:
- Email: admin@nmmlaw.com
- Password: admin123
Test Account:
- Email: test@example.com
- Password: testpass123
Database:
- Database: casevault_db
- User: casevault_user
- Password: casevault_pass123
- Frontend: 5173 (Vite dev server)
- Backend: 8000 (Django server)
- Database: 5432 (PostgreSQL)
Backend:
- Settings:
backend/casevault/settings.py - Models:
backend/core/models.py - API Views:
backend/api/views.py - URLs:
backend/api/urls.py
Frontend:
- Main App:
frontend/src/App.tsx - Components:
frontend/src/components/ - Services:
frontend/src/services/ - Styles:
frontend/src/index.css
Backend:
python manage.py runserver # Start server
python manage.py migrate # Run migrations
python manage.py makemigrations # Create migrations
python manage.py createsuperuser # Create admin user
python manage.py shell # Django shell
python manage.py test # Run testsFrontend:
npm run dev # Start dev server
npm run build # Build for production
npm run preview # Preview production build
npm install # Install dependenciesDatabase:
psql -U casevault_user -d casevault_db # Connect to database
pg_dump casevault_db > backup.sql # Backup database
psql casevault_db < backup.sql # Restore databaseEnd of Manual
Version: 1.0.0
Last Updated: December 12, 2025
Maintained by: Neyra Marcos Mendez & Jungco Law Office
For questions or support, please refer to the Support & Contact section.