{"id":50551726,"url":"https://github.com/tsofnatmaman/propertymonitoringdashboard","last_synced_at":"2026-06-04T04:01:30.324Z","repository":{"id":347886141,"uuid":"1195502868","full_name":"TsofnatMaman/PropertyMonitoringDashboard","owner":"TsofnatMaman","description":"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.","archived":false,"fork":false,"pushed_at":"2026-03-29T23:33:06.000Z","size":130,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-30T00:48:39.474Z","etag":null,"topics":["fullstack","monitoring-system","react","typescript","web-scraping"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TsofnatMaman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-29T18:38:17.000Z","updated_at":"2026-03-29T23:42:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/TsofnatMaman/PropertyMonitoringDashboard","commit_stats":null,"previous_names":["tsofnatmaman/propertymonitoringdashboard"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/TsofnatMaman/PropertyMonitoringDashboard","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TsofnatMaman%2FPropertyMonitoringDashboard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TsofnatMaman%2FPropertyMonitoringDashboard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TsofnatMaman%2FPropertyMonitoringDashboard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TsofnatMaman%2FPropertyMonitoringDashboard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TsofnatMaman","download_url":"https://codeload.github.com/TsofnatMaman/PropertyMonitoringDashboard/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TsofnatMaman%2FPropertyMonitoringDashboard/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33888302,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fullstack","monitoring-system","react","typescript","web-scraping"],"created_at":"2026-06-04T04:01:29.120Z","updated_at":"2026-06-04T04:01:30.316Z","avatar_url":"https://github.com/TsofnatMaman.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"﻿# 🏢 Property Monitoring Dashboard\n\nA system for monitoring property inspection activity from LAHD, designed to help property managers quickly identify new, important, and urgent cases across company-owned properties.\n\n---\n\n## 🎯 Business Goal\n\nProperty managers need to:\n\n* Detect new inspections or case activity as soon as possible\n* Understand the current status of each case at a glance\n* Identify urgent or high-risk cases quickly\n* Make fast, informed decisions with minimal noise\n\nThis system focuses on surfacing the **right information, at the right time**, without overwhelming the user.\n\n---\n\n## 🧠 Solution Overview\n\nThe system provides a focused monitoring dashboard for inspection activity across selected properties.\n\n* Users select which properties (APNs) to track\n* Data is synchronized daily from the LAHD website\n* Manual sync is available through the UI\n* Cases are enriched with computed flags to highlight their importance\n\nThe dashboard enables users to immediately understand:\n\n* What’s new\n* What requires attention\n* What is urgent\n\n---\n\n## 🏗 Architecture\n\n### Server\n\n**Tech:** Express + TypeScript + SQLite\n\nResponsibilities:\n\n* Scraping LAHD property and case data\n* Extracting case activity and latest status\n* Normalizing and storing data\n* Computing flags (Open, Attention, Urgent, New)\n* Exposing APIs for properties, sync, and monitoring\n\n---\n\n### Client\n\n**Tech:** React + Vite\n\nResponsibilities:\n\n* Managing tracked properties\n* Displaying a cases dashboard\n* Filtering and searching cases\n* Highlighting important cases using visual flags\n* Triggering manual sync operations\n* Showing sync progress\n\n---\n\n## 🗂 Data Model\n\nThis section lists the fields stored and **why they matter** for the dashboard use case.\n\n### `properties`\n\n| Field         | Description                                                        |\n| ------------- | ------------------------------------------------------------------ |\n| `id`          | Internal primary key used for reliable joins and relational integrity. |\n| `apn`         | Unique external property identifier used for LAHD scraping and tracking. |\n| `description` | User-defined label (address/name) to help users quickly identify the property in UI. |\n| `created_at`  | Creation timestamp kept mainly for traceability and debugging.      |\n\n---\n\n### `cases`\n\n| Field                  | Description                                                                 |\n| ---------------------- | --------------------------------------------------------------------------- |\n| `id`                   | Primary key used for reliable joins and relational integrity.              |\n| `property_id`          | Reference to the related property, linking every case to its property.     |\n| `case_number`          | Case identifier used to match incoming case updates from the source.       |\n| `case_type`            | LAHD case type label used for quick classification and flag logic.         |\n| `case_type_id`         | LAHD case type ID that disambiguates identity together with `case_number`. |\n| `latest_status`        | Most recent known status used for current state display and priority flags. |\n| `latest_activity_date` | Last activity timestamp used for recency sorting and \"what's new\".         |\n| `has_new_activity`     | Stored marker that preserves recent-activity signal between sync cycles.   |\n\n### `sync_runs`\n\nMainly used for sync monitoring and debugging.\n\n\nThese fields allow the system to determine:\n\n* Case state\n* Recency of activity\n* Priority level for display\n\n---\n\n## 🚩 Flags Logic\n\nFlags are computed on the server to ensure consistent behavior across the UI:\n\n* **isOpen**\n  Case is considered open unless marked as closed or resolved\n\n* **needsAttention**\n  Triggered for cases such as:\n\n  * violations\n  * non-compliance\n  * follow-ups\n  * re-inspections\n\n* **isUrgent**\n  Triggered for high-risk situations such as:\n\n  * order to comply\n  * final notice\n  * hazardous conditions\n\n* **hasNewActivity**\n\n  * Activity occurred after the last sync\n  * OR within the last 100 days\n\nThese flags allow the dashboard to prioritize cases effectively.\n\n\n### ⚠️ Important Note on Flag Logic\n\n**The classification and flag logic is example code only.**\n\nThe flags (Open, Needs Attention, Urgent, New Activity) are computed using simplified heuristics based on case status keywords. This logic is:\n\n* **Intentionally simple** for demonstration purposes\n* **Easy to customize** on the server side\n* **Not production-tested** against real LAHD data patterns\n\n**To adapt for your use case:**\n\n1. Review the flag logic in [`server/src/services/cases/case-labels.service.ts`](server/src/services/cases/case-labels.service.ts)\n2. Adjust the status markers in [`server/src/services/cases/case-classifiers.ts`](server/src/services/cases/case-classifiers.ts)\n3. Add real case data and test the output\n4. Refine keywords and classification rules as needed\n\nThis design allows quick iteration without changing the rest of the system.\n\n---\n\n## ▲ Case Priority Scoring\n\nIn addition to the flags, the server sorts cases by a simple priority score so the most important items appear first.\n\nThe score is computed as:\n\n```\nscore = (isUrgent ? 8 : 0)\n      + (needsAttention ? 4 : 0)\n      + (hasNewActivity ? 2 : 0)\n      + (isOpen ? 1 : 0)\n```\n\nCases are ordered by:\n\n1. Highest score first\n2. Most recent `latest_activity_date` if scores are equal\n\nThis is intentionally simple and easy to adjust in\n`server/src/services/monitoring/overview.service.ts` and the flag rules in\n`server/src/services/cases/case-classifiers.ts`.\n\n---\n\n## 🔄 Data Synchronization\n\nThe system retrieves data in two stages:\n\n1. Property case lists (by APN)\n2. Individual case activity pages (for latest status and timestamps)\n\nFeatures:\n\n* Retry mechanism\n* Timeout handling\n* Exponential backoff\n\nSync runs:\n\n* Automatically once per day\n* Manually via the UI\n\n---\n\n## 🌐 API Overview\n\n| Endpoint                                | Description                      |\n| --------------------------------------- | -------------------------------- |\n| `GET /api/properties`                   | List tracked properties          |\n| `POST /api/properties`                  | Add or update a property         |\n| `POST /api/monitoring/sync-all`         | Sync all properties              |\n| `POST /api/monitoring/:apn/sync`        | Sync a single property           |\n| `GET /api/monitoring/sync-all/progress` | Get sync progress                |\n| `GET /api/monitoring/cases/overview`    | Get cases with flags and summary |\n\n---\n\n## 🖥 Dashboard Capabilities\n\n* Case table with:\n\n  * Case number (link to source)\n  * Type\n  * Latest status\n  * Latest activity date\n  * Visual flags (Open / Attention / Urgent / New)\n\n* Summary cards:\n\n  * Total cases\n  * Open cases\n  * Needs attention\n  * Urgent\n\n* Filters:\n\n  * Search (APN, case number, status, etc.)\n  * Open only\n  * Needs attention\n  * Urgent\n\n* Sync progress view:\n\n  * Property-level progress\n  * Case-level progress\n  * Success / failure metrics\n\n---\n\n## 🚀 Running Instructions\n\n###  Option 1: Docker (Recommended)\n\n```bash\ndocker-compose up --build\n```\n\nThen open your browser to:\n\n* **Management Properties**: http://localhost:5173/properties\n* **Dashboard**: http://localhost:5173\n\nThe system DB initializes automatically with the default property (APN: 2654002037).\n\n(The server API is accessible via proxy at `/api` - no direct port exposure)\n\n### Option 2: Manual Setup (Development)\n\n**Server:**\n```bash\ncd server\nnpm install\nnpm run dev\n# Runs on http://localhost:3000\n```\n\n**Client (new terminal):**\n```bash\ncd client\nnpm install\nnpm run dev\n# Runs on http://localhost:5173\n```\n\n**Run Server Tests:**\n```bash\ncd server\nnpm test\n```\n\n### Environment Variables\n\nThe system uses sensible defaults, but you can customize via `.env` or `docker-compose.yml`:\n\n* `PORT` – Server port (default: 3000)\n* `SCRAPE_TIMEOUT_MS` – Timeout for LAHD scraping (default: 30000 = 30 seconds)\n* `SCRAPE_RETRY_ATTEMPTS` – Retry attempts on timeout (default: 4)\n* `SCRAPE_RETRY_BASE_DELAY_MS` – Delay between retries (default: 2000 = 2 seconds, exponential backoff)\n* `DAILY_SYNC_CRON` – Cron schedule for daily sync (default: \"0 2 * * *\" – 2 AM UTC)\n* `DAILY_SYNC_TIMEZONE` – Timezone for cron (default: \"Asia/Jerusalem\")\n* `LOG_LEVEL` – Logging level (default: \"info\", options: \"debug\", \"info\", \"warn\", \"error\")\n\n---\n\n## 🚀 Future Improvements\n\nIf given more time, I would extend the system with:\n\n* Automated tests (unit + integration)\n* Smarter sync policies (e.g. closed cases updated less frequently)\n* Database optimizations (batching, indexing)\n* Data retention / cleanup strategy\n* User-controlled flag overrides\n* Multi-user support\n* Subscriptions / notifications (alerts on urgent cases)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftsofnatmaman%2Fpropertymonitoringdashboard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftsofnatmaman%2Fpropertymonitoringdashboard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftsofnatmaman%2Fpropertymonitoringdashboard/lists"}