22d0ecb330
Backend:
- HealthRequest model: TrackingCode (DR-XXXXXX), Diagnosis,
DoctorReply, RepliedAt fields
- Runtime migration: ALTER TABLE adds 4 new columns to existing DB
- POST /api/health-request: auto-generates tracking code, returns it
- PUT /api/health-requests/{id}/reply: doctor sets diagnosis + reply
- GET /api/health-request/track/{code}: public lookup by tracking code
- GET /api/health-requests?phone=: filter history by phone number
Admin panel:
- Request table shows tracking code column (gold badge)
- Detail modal (680px): tracking code header, patient info, full message
- Previous doctor reply shown in green box if exists
- Reply form: diagnosis input + textarea for doctor message
- History panel: all requests from same phone, click to switch
- 'پاسخ / مشاهده' button opens reply modal directly
Frontend:
- After form submit: shows tracking code in green box to user
(format: DR-XXXXXX, stays visible 8 seconds)
- Box auto-hides and form resets after timeout
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
194 lines
9.5 KiB
C#
194 lines
9.5 KiB
C#
using System.ComponentModel.DataAnnotations;
|
|
|
|
namespace DrSousan.Api.Models;
|
|
|
|
// ─── Site Settings (key-value store per section) ─────────────────────────────
|
|
public class SiteSetting
|
|
{
|
|
public int Id { get; set; }
|
|
[MaxLength(100)] public string Key { get; set; } = "";
|
|
public string Value { get; set; } = "";
|
|
[MaxLength(50)] public string Section { get; set; } = "";
|
|
}
|
|
|
|
// ─── Service card ─────────────────────────────────────────────────────────────
|
|
public class Service
|
|
{
|
|
public int Id { get; set; }
|
|
[MaxLength(200)] public string Title { get; set; } = "";
|
|
public string Description { get; set; } = "";
|
|
[MaxLength(500)] public string IconSvg { get; set; } = "";
|
|
[MaxLength(500)] public string BeforeImageUrl { get; set; } = "";
|
|
[MaxLength(500)] public string AfterImageUrl { get; set; } = "";
|
|
public int Order { get; set; }
|
|
public bool IsActive { get; set; } = true;
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
}
|
|
|
|
// ─── Gallery item ─────────────────────────────────────────────────────────────
|
|
public class GalleryItem
|
|
{
|
|
public int Id { get; set; }
|
|
[MaxLength(500)] public string ImageUrl { get; set; } = "";
|
|
[MaxLength(500)] public string BeforeImageUrl { get; set; } = "";
|
|
[MaxLength(500)] public string AfterImageUrl { get; set; } = "";
|
|
[MaxLength(100)] public string Category { get; set; } = "";
|
|
[MaxLength(300)] public string Caption { get; set; } = "";
|
|
public int Order { get; set; }
|
|
public bool IsActive { get; set; } = true;
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
}
|
|
|
|
// ─── Testimonial ──────────────────────────────────────────────────────────────
|
|
public class Testimonial
|
|
{
|
|
public int Id { get; set; }
|
|
[MaxLength(100)] public string AuthorName { get; set; } = "";
|
|
[MaxLength(10)] public string AuthorEmoji { get; set; } = "👩";
|
|
public string Text { get; set; } = "";
|
|
public int Rating { get; set; } = 5;
|
|
[MaxLength(50)] public string Date { get; set; } = "";
|
|
public bool IsActive { get; set; } = true;
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
}
|
|
|
|
// ─── Blog category ────────────────────────────────────────────────────────────
|
|
public class BlogCategory
|
|
{
|
|
public int Id { get; set; }
|
|
[MaxLength(100)] public string Name { get; set; } = "";
|
|
[MaxLength(120)] public string Slug { get; set; } = "";
|
|
public string Description { get; set; } = "";
|
|
public ICollection<BlogPost> Posts { get; set; } = new List<BlogPost>();
|
|
}
|
|
|
|
// ─── Blog post ────────────────────────────────────────────────────────────────
|
|
public class BlogPost
|
|
{
|
|
public int Id { get; set; }
|
|
|
|
// Content
|
|
[MaxLength(300)] public string Title { get; set; } = "";
|
|
[MaxLength(320)] public string Slug { get; set; } = "";
|
|
public string Excerpt { get; set; } = "";
|
|
public string Content { get; set; } = "";
|
|
[MaxLength(500)] public string FeaturedImage { get; set; } = "";
|
|
[MaxLength(100)] public string Author { get; set; } = "دکتر سوسن آلطه";
|
|
|
|
// SEO
|
|
[MaxLength(70)] public string MetaTitle { get; set; } = "";
|
|
[MaxLength(160)] public string MetaDescription { get; set; } = "";
|
|
[MaxLength(100)] public string FocusKeyword { get; set; } = "";
|
|
public string Keywords { get; set; } = ""; // comma-separated
|
|
[MaxLength(500)] public string OgImage { get; set; } = "";
|
|
|
|
// Schema.org
|
|
[MaxLength(50)] public string ArticleType { get; set; } = "MedicalWebPage";
|
|
|
|
// Status
|
|
public bool IsPublished { get; set; } = false;
|
|
public DateTime? PublishedAt { get; set; }
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
|
|
|
// Metrics
|
|
public int ViewCount { get; set; } = 0;
|
|
public int ReadingTimeMinutes { get; set; } = 5;
|
|
|
|
// Relations
|
|
public int? CategoryId { get; set; }
|
|
public BlogCategory? Category { get; set; }
|
|
}
|
|
|
|
// ─── Blog comment ────────────────────────────────────────────────────────────
|
|
public class Comment
|
|
{
|
|
public int Id { get; set; }
|
|
[MaxLength(100)] public string AuthorName { get; set; } = "";
|
|
[MaxLength(200)] public string AuthorEmail { get; set; } = "";
|
|
public string Body { get; set; } = "";
|
|
public bool IsApproved { get; set; } = false;
|
|
public bool IsAdminReply { get; set; } = false;
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
// Post relation
|
|
public int BlogPostId { get; set; }
|
|
public BlogPost? Post { get; set; }
|
|
// Self-referential reply
|
|
public int? ParentId { get; set; }
|
|
public Comment? Parent { get; set; }
|
|
public ICollection<Comment> Replies { get; set; } = new List<Comment>();
|
|
}
|
|
|
|
// ─── FAQ ─────────────────────────────────────────────────────────────────────
|
|
public class Faq
|
|
{
|
|
public int Id { get; set; }
|
|
public string Question { get; set; } = "";
|
|
public string Answer { get; set; } = "";
|
|
public int Order { get; set; }
|
|
public bool IsActive { get; set; } = true;
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
}
|
|
|
|
// ─── Patient ──────────────────────────────────────────────────────────────────
|
|
public class Patient
|
|
{
|
|
public int Id { get; set; }
|
|
[MaxLength(150)] public string FullName { get; set; } = "";
|
|
[MaxLength(20)] public string PhoneNumber { get; set; } = "";
|
|
[MaxLength(200)] public string Email { get; set; } = "";
|
|
public int Age { get; set; }
|
|
public decimal Weight { get; set; } // kg
|
|
public decimal Height { get; set; } // cm
|
|
[MaxLength(10)] public string Gender { get; set; } = ""; // مرد / زن
|
|
[MaxLength(10)] public string BloodType { get; set; } = "";
|
|
public string DiseaseHistory { get; set; } = "";
|
|
public string Allergies { get; set; } = "";
|
|
public string Medications { get; set; } = "";
|
|
public string Notes { get; set; } = "";
|
|
[MaxLength(20)] public string Category { get; set; } = "beauty"; // beauty | health
|
|
public bool IsActive { get; set; } = true;
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
public ICollection<PatientVisit> Visits { get; set; } = new List<PatientVisit>();
|
|
}
|
|
|
|
// ─── Patient Visit / Doctor Note ──────────────────────────────────────────────
|
|
public class PatientVisit
|
|
{
|
|
public int Id { get; set; }
|
|
public int PatientId { get; set; }
|
|
public Patient? Patient { get; set; }
|
|
[MaxLength(300)] public string Title { get; set; } = "";
|
|
public string Content { get; set; } = "";
|
|
public string Prescription { get; set; } = ""; // دارو / تجویز
|
|
[MaxLength(50)] public string VisitType { get; set; } = "ویزیت"; // ویزیت | آزمایش | پروسیجر
|
|
public DateTime VisitDate { get; set; } = DateTime.UtcNow;
|
|
public DateTime? NextVisitDate { get; set; }
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
}
|
|
|
|
// ─── Health / Appointment Request (public form) ───────────────────────────────
|
|
public class HealthRequest
|
|
{
|
|
public int Id { get; set; }
|
|
[MaxLength(20)] public string TrackingCode { get; set; } = ""; // e.g. DR-A3F7K2
|
|
[MaxLength(150)] public string FullName { get; set; } = "";
|
|
[MaxLength(20)] public string PhoneNumber { get; set; } = "";
|
|
[MaxLength(200)] public string Email { get; set; } = "";
|
|
public string Message { get; set; } = "";
|
|
[MaxLength(20)] public string Category { get; set; } = "beauty"; // beauty | health
|
|
public bool IsHandled { get; set; } = false;
|
|
// Doctor response
|
|
public string Diagnosis { get; set; } = ""; // پزشک: تشخیص
|
|
public string DoctorReply { get; set; } = ""; // پزشک: پاسخ/توضیح
|
|
public DateTime? RepliedAt { get; set; }
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
}
|
|
|
|
// ─── DTOs ─────────────────────────────────────────────────────────────────────
|
|
public record LoginRequest(string Username, string Password);
|
|
public record DoctorReplyDto(string? Diagnosis, string? DoctorReply);
|
|
public record ChangePasswordRequest(string CurrentPassword, string NewPassword);
|
|
public record SettingDto(string Key, string Value);
|
|
public record BulkSettingsDto(Dictionary<string, string> Settings);
|