https://github.com/tsofnatmaman/propertymonitoringdashboard
A system for monitoring property inspection activity from LAHD, designed to help property managers quickly identify new, important, and urgent cases across company-owned properties.
https://github.com/tsofnatmaman/propertymonitoringdashboard
fullstack monitoring-system react typescript web-scraping
Last synced: 4 days ago
JSON representation
A system for monitoring property inspection activity from LAHD, designed to help property managers quickly identify new, important, and urgent cases across company-owned properties.
- Host: GitHub
- URL: https://github.com/tsofnatmaman/propertymonitoringdashboard
- Owner: TsofnatMaman
- Created: 2026-03-29T18:38:17.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-03-29T23:33:06.000Z (2 months ago)
- Last Synced: 2026-03-30T00:48:39.474Z (2 months ago)
- Topics: fullstack, monitoring-system, react, typescript, web-scraping
- Language: TypeScript
- Homepage:
- Size: 127 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
ο»Ώ# π’ Property Monitoring Dashboard
A system for monitoring property inspection activity from LAHD, designed to help property managers quickly identify new, important, and urgent cases across company-owned properties.
---
## π― Business Goal
Property managers need to:
* Detect new inspections or case activity as soon as possible
* Understand the current status of each case at a glance
* Identify urgent or high-risk cases quickly
* Make fast, informed decisions with minimal noise
This system focuses on surfacing the **right information, at the right time**, without overwhelming the user.
---
## π§ Solution Overview
The system provides a focused monitoring dashboard for inspection activity across selected properties.
* Users select which properties (APNs) to track
* Data is synchronized daily from the LAHD website
* Manual sync is available through the UI
* Cases are enriched with computed flags to highlight their importance
The dashboard enables users to immediately understand:
* Whatβs new
* What requires attention
* What is urgent
---
## π Architecture
### Server
**Tech:** Express + TypeScript + SQLite
Responsibilities:
* Scraping LAHD property and case data
* Extracting case activity and latest status
* Normalizing and storing data
* Computing flags (Open, Attention, Urgent, New)
* Exposing APIs for properties, sync, and monitoring
---
### Client
**Tech:** React + Vite
Responsibilities:
* Managing tracked properties
* Displaying a cases dashboard
* Filtering and searching cases
* Highlighting important cases using visual flags
* Triggering manual sync operations
* Showing sync progress
---
## π Data Model
This section lists the fields stored and **why they matter** for the dashboard use case.
### `properties`
| Field | Description |
| ------------- | ------------------------------------------------------------------ |
| `id` | Internal primary key used for reliable joins and relational integrity. |
| `apn` | Unique external property identifier used for LAHD scraping and tracking. |
| `description` | User-defined label (address/name) to help users quickly identify the property in UI. |
| `created_at` | Creation timestamp kept mainly for traceability and debugging. |
---
### `cases`
| Field | Description |
| ---------------------- | --------------------------------------------------------------------------- |
| `id` | Primary key used for reliable joins and relational integrity. |
| `property_id` | Reference to the related property, linking every case to its property. |
| `case_number` | Case identifier used to match incoming case updates from the source. |
| `case_type` | LAHD case type label used for quick classification and flag logic. |
| `case_type_id` | LAHD case type ID that disambiguates identity together with `case_number`. |
| `latest_status` | Most recent known status used for current state display and priority flags. |
| `latest_activity_date` | Last activity timestamp used for recency sorting and "what's new". |
| `has_new_activity` | Stored marker that preserves recent-activity signal between sync cycles. |
### `sync_runs`
Mainly used for sync monitoring and debugging.
These fields allow the system to determine:
* Case state
* Recency of activity
* Priority level for display
---
## π© Flags Logic
Flags are computed on the server to ensure consistent behavior across the UI:
* **isOpen**
Case is considered open unless marked as closed or resolved
* **needsAttention**
Triggered for cases such as:
* violations
* non-compliance
* follow-ups
* re-inspections
* **isUrgent**
Triggered for high-risk situations such as:
* order to comply
* final notice
* hazardous conditions
* **hasNewActivity**
* Activity occurred after the last sync
* OR within the last 100 days
These flags allow the dashboard to prioritize cases effectively.
### β οΈ Important Note on Flag Logic
**The classification and flag logic is example code only.**
The flags (Open, Needs Attention, Urgent, New Activity) are computed using simplified heuristics based on case status keywords. This logic is:
* **Intentionally simple** for demonstration purposes
* **Easy to customize** on the server side
* **Not production-tested** against real LAHD data patterns
**To adapt for your use case:**
1. Review the flag logic in [`server/src/services/cases/case-labels.service.ts`](server/src/services/cases/case-labels.service.ts)
2. Adjust the status markers in [`server/src/services/cases/case-classifiers.ts`](server/src/services/cases/case-classifiers.ts)
3. Add real case data and test the output
4. Refine keywords and classification rules as needed
This design allows quick iteration without changing the rest of the system.
---
## β² Case Priority Scoring
In addition to the flags, the server sorts cases by a simple priority score so the most important items appear first.
The score is computed as:
```
score = (isUrgent ? 8 : 0)
+ (needsAttention ? 4 : 0)
+ (hasNewActivity ? 2 : 0)
+ (isOpen ? 1 : 0)
```
Cases are ordered by:
1. Highest score first
2. Most recent `latest_activity_date` if scores are equal
This is intentionally simple and easy to adjust in
`server/src/services/monitoring/overview.service.ts` and the flag rules in
`server/src/services/cases/case-classifiers.ts`.
---
## π Data Synchronization
The system retrieves data in two stages:
1. Property case lists (by APN)
2. Individual case activity pages (for latest status and timestamps)
Features:
* Retry mechanism
* Timeout handling
* Exponential backoff
Sync runs:
* Automatically once per day
* Manually via the UI
---
## π API Overview
| Endpoint | Description |
| --------------------------------------- | -------------------------------- |
| `GET /api/properties` | List tracked properties |
| `POST /api/properties` | Add or update a property |
| `POST /api/monitoring/sync-all` | Sync all properties |
| `POST /api/monitoring/:apn/sync` | Sync a single property |
| `GET /api/monitoring/sync-all/progress` | Get sync progress |
| `GET /api/monitoring/cases/overview` | Get cases with flags and summary |
---
## π₯ Dashboard Capabilities
* Case table with:
* Case number (link to source)
* Type
* Latest status
* Latest activity date
* Visual flags (Open / Attention / Urgent / New)
* Summary cards:
* Total cases
* Open cases
* Needs attention
* Urgent
* Filters:
* Search (APN, case number, status, etc.)
* Open only
* Needs attention
* Urgent
* Sync progress view:
* Property-level progress
* Case-level progress
* Success / failure metrics
---
## π Running Instructions
### Option 1: Docker (Recommended)
```bash
docker-compose up --build
```
Then open your browser to:
* **Management Properties**: http://localhost:5173/properties
* **Dashboard**: http://localhost:5173
The system DB initializes automatically with the default property (APN: 2654002037).
(The server API is accessible via proxy at `/api` - no direct port exposure)
### Option 2: Manual Setup (Development)
**Server:**
```bash
cd server
npm install
npm run dev
# Runs on http://localhost:3000
```
**Client (new terminal):**
```bash
cd client
npm install
npm run dev
# Runs on http://localhost:5173
```
**Run Server Tests:**
```bash
cd server
npm test
```
### Environment Variables
The system uses sensible defaults, but you can customize via `.env` or `docker-compose.yml`:
* `PORT` β Server port (default: 3000)
* `SCRAPE_TIMEOUT_MS` β Timeout for LAHD scraping (default: 30000 = 30 seconds)
* `SCRAPE_RETRY_ATTEMPTS` β Retry attempts on timeout (default: 4)
* `SCRAPE_RETRY_BASE_DELAY_MS` β Delay between retries (default: 2000 = 2 seconds, exponential backoff)
* `DAILY_SYNC_CRON` β Cron schedule for daily sync (default: "0 2 * * *" β 2 AM UTC)
* `DAILY_SYNC_TIMEZONE` β Timezone for cron (default: "Asia/Jerusalem")
* `LOG_LEVEL` β Logging level (default: "info", options: "debug", "info", "warn", "error")
---
## π Future Improvements
If given more time, I would extend the system with:
* Automated tests (unit + integration)
* Smarter sync policies (e.g. closed cases updated less frequently)
* Database optimizations (batching, indexing)
* Data retention / cleanup strategy
* User-controlled flag overrides
* Multi-user support
* Subscriptions / notifications (alerts on urgent cases)