Initial commit — Hamkadr (همکادر) healthcare-staffing marketplace
ASP.NET Core 10 Razor Pages + PostgreSQL/EF Core. RTL Persian, Jalali dates, self-hosted Vazirmatn, teal/coral brand. Features: - Shift listings: browse/filter (city, district, role, type, pay), weekly Jalali calendar, detail + interest handoff, near-me distance sort - Hiring (استخدام) listings with employment type + salary range - Pattern-engine recommendations + anonymous interest tracking (visitor cookie) - Heuristic Persian listing-parser + admin queue (raw channel post → shift/job) - Phone-OTP cookie auth + visitor-history linking + profile Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
# همکادر — Hamkadr
|
||||
|
||||
سامانهی واسط میان **کادر درمان** (پزشک، پرستار، ماما، تکنسین) و **بیمارستانها و کلینیکها**
|
||||
برای یافتن **شیفت و موقعیت استخدامی**. بهجای گشتن در کانالهای تلگرام/بله و دیوار،
|
||||
همهی فرصتها یکجا — بر اساس مرکز درمانی، محل و تقویم هفتگی شمسی، با **پیشنهاد هوشمند**
|
||||
متناسب با علاقهمندی و فعالیت هر فرد.
|
||||
|
||||
A two-sided healthcare-staffing marketplace (shifts **and** permanent hiring) connecting all
|
||||
clinical staff with hospitals/clinics. See [PLAN.md](PLAN.md) and [FEATURES.md](FEATURES.md).
|
||||
|
||||
## Stack
|
||||
- **ASP.NET Core (Razor Pages), .NET 10** — server-rendered for SEO
|
||||
- **PostgreSQL + EF Core (Npgsql)**
|
||||
- RTL Persian UI, Jalali (Shamsi) dates via `System.Globalization.PersianCalendar`
|
||||
- **Pattern-engine recommendations** + anonymous interest tracking (cookie-based visitor id)
|
||||
- **Self-hosted Vazirmatn font** (`wwwroot/fonts`, no CDN), teal + coral brand palette
|
||||
- **Location filters:** city → district/neighborhood, plus **"near me"** (browser geolocation → Haversine distance sort)
|
||||
|
||||
## Run locally
|
||||
|
||||
```bash
|
||||
# 1. Start PostgreSQL (host port 5433)
|
||||
docker compose up -d
|
||||
|
||||
# 2. Run the web app (applies migrations + seeds Tehran sample data on startup)
|
||||
dotnet run --project src/JobsMedical.Web
|
||||
```
|
||||
|
||||
Then open the URL printed in the console (e.g. http://localhost:5020).
|
||||
|
||||
### Pages
|
||||
| Route | Page |
|
||||
|---|---|
|
||||
| `/` | خانه — hero, role/city search, **پیشنهادهای ویژه شما**, latest shifts |
|
||||
| `/Shifts` | فهرست با فیلتر (شهر، **محله/منطقه**، نقش، مرکز، نوع شیفت، حقوق) + **«نزدیک من»** |
|
||||
| `/Shifts/Details/{id}` | جزئیات + اعلام تمایل / ذخیره / رد (همه رویدادها ثبت میشوند) |
|
||||
| `/Jobs` | موقعیتهای **استخدامی** با فیلتر (شهر، محله، نقش، نوع همکاری) + «نزدیک من» |
|
||||
| `/Jobs/Details/{id}` | جزئیات موقعیت استخدامی + اعلام تمایل / ذخیره / رد |
|
||||
| `/Calendar` | تقویم هفتگی شمسی شیفتها |
|
||||
| `/Facilities` | فهرست مراکز درمانی |
|
||||
| `/Preferences` | تنظیم علاقهمندیها (نقش، شهر، نوع شیفت، حقوق) |
|
||||
| `/Account/Login` | ورود/ثبتنام با **کد یکبارمصرف موبایل (OTP)** |
|
||||
| `/Account/Profile` | پروفایل: شیفتها/موقعیتهای ذخیرهشده و اعلام تمایلها |
|
||||
| `/Admin` | پنل مدیریت (نقش Admin): صف آگهیهای خام |
|
||||
| `/Admin/Review/{id}` | بررسی خودکار (پارسر) و انتشار آگهی بهصورت شیفت یا استخدام |
|
||||
|
||||
## How recommendations work (Stage 1 — pattern engine)
|
||||
`RecommendationService` scores open shifts against (a) explicit `UserPreferences` and (b) recent
|
||||
`InterestEvent`s (view/save/apply/dismiss), and returns the top matches **each with a Persian
|
||||
reason** ("متناسب با نقش مورد علاقه شما"، "چون به فرصتهای پرستار علاقه نشان دادی"). Fully
|
||||
explainable, no AI infra, works from the first visit. The behavioral log is the fuel for the
|
||||
later collaborative + ML/embedding stages (see [FEATURES.md](FEATURES.md) Part A).
|
||||
|
||||
## Project status
|
||||
Done: multi-role domain model, Postgres + migrations, RTL shell, browse/filter (incl. role,
|
||||
district, near-me), weekly Jalali calendar, shift detail + interest handoff, interest tracking +
|
||||
pattern-engine recommendation feed + preferences, self-hosted Vazirmatn + teal/coral palette,
|
||||
**hiring (استخدام) listings**, **admin queue + heuristic listing-parser** (raw channel post →
|
||||
structured shift/job), **phone-OTP auth + visitor-history linking + profile**, Tehran seed data.
|
||||
|
||||
### Listing parser (Stage 1)
|
||||
`IListingParser` / `HeuristicListingParser` extracts kind (shift vs hire), role, shift type,
|
||||
employment type, pay, city/district, and phone from a raw Persian post via keyword + regex
|
||||
heuristics — **no AI dependency** (LLM APIs are blocked from Iran). Admin reviews the prefilled
|
||||
form and publishes. Swap in an `LlmListingParser` later behind the same interface.
|
||||
|
||||
### Auth
|
||||
Phone OTP via `OtpService` (in-memory codes; dev shows the code on screen — wire Kavenegar/SMS.ir
|
||||
for prod). Cookie auth; the configured `Auth:AdminPhone` gets the `Admin` role. On login the
|
||||
anonymous `hk_vid` visitor (and its interest history) is linked to the user account.
|
||||
|
||||
Next:
|
||||
- Unified recommendations across shifts **and** jobs (currently shift-focused)
|
||||
- Self-serve facility posting + dashboards; verification badges
|
||||
- Real SMS gateway + Neshan/Balad interactive maps
|
||||
- LLM-backed listing parser; automated channel aggregation worker
|
||||
Reference in New Issue
Block a user