Initial commit
This commit is contained in:
@@ -0,0 +1,323 @@
|
||||
@model PowderCoating.Application.DTOs.Appointment.AppointmentDto
|
||||
|
||||
@{
|
||||
ViewData["Title"] = $"Appointment {Model.AppointmentNumber}";
|
||||
ViewData["PageIcon"] = "bi-calendar-event";
|
||||
ViewData["PageHelpTitle"] = "Appointment Details";
|
||||
ViewData["PageHelpContent"] = "View all details for this appointment. Edit to update status or record actual times. Deleting permanently removes the record — consider setting status to Cancelled instead to preserve history.";
|
||||
}
|
||||
|
||||
<div class="d-flex justify-content-end gap-2 mb-4">
|
||||
<a asp-action="Edit" asp-route-id="@Model.Id" class="btn btn-outline-primary">
|
||||
<i class="bi bi-pencil"></i> Edit
|
||||
</a>
|
||||
<a asp-action="Index" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-arrow-left"></i> Back to List
|
||||
</a>
|
||||
</div><div class="row g-4">
|
||||
<!-- Left Column - Customer & Schedule Info -->
|
||||
<div class="col-lg-6">
|
||||
<!-- Customer Information -->
|
||||
<div class="card mb-3">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h5 class="mb-0"><i class="bi bi-person-circle me-2"></i>Customer Information</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (Model.CustomerId.HasValue && !string.IsNullOrEmpty(Model.CustomerName))
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-4 text-muted">Customer:</div>
|
||||
<div class="col-sm-8">
|
||||
<strong>@Model.CustomerName</strong>
|
||||
</div>
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(Model.CustomerPhone))
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-4 text-muted">Phone:</div>
|
||||
<div class="col-sm-8">
|
||||
<a href="tel:@Model.CustomerPhone">@Model.CustomerPhone</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.CustomerEmail))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-4 text-muted">Email:</div>
|
||||
<div class="col-sm-8">
|
||||
<a href="mailto:@Model.CustomerEmail">@Model.CustomerEmail</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="alert alert-info mb-0">
|
||||
<i class="bi bi-info-circle me-2"></i>
|
||||
<strong>Internal Appointment</strong><br />
|
||||
<small>This appointment is not associated with a customer.</small>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Schedule Information -->
|
||||
<div class="card mb-3">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h5 class="mb-0"><i class="bi bi-calendar-event me-2"></i>Schedule</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-4 text-muted">Date:</div>
|
||||
<div class="col-sm-8">
|
||||
<strong>@Model.ScheduledStartTime.ToString("dddd, MMMM dd, yyyy")</strong>
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.IsAllDay)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-4 text-muted">Time:</div>
|
||||
<div class="col-sm-8">
|
||||
<span class="badge bg-secondary">All Day</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-4 text-muted">Start Time:</div>
|
||||
<div class="col-sm-8">@Model.ScheduledStartTime.ToString("h:mm tt")</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-4 text-muted">End Time:</div>
|
||||
<div class="col-sm-8">@Model.ScheduledEndTime.ToString("h:mm tt")</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 text-muted">Duration:</div>
|
||||
<div class="col-sm-8">
|
||||
@{
|
||||
var duration = Model.ScheduledEndTime - Model.ScheduledStartTime;
|
||||
var hours = (int)duration.TotalHours;
|
||||
var minutes = duration.Minutes;
|
||||
}
|
||||
@if (hours > 0)
|
||||
{
|
||||
<span>@hours hour@(hours != 1 ? "s" : "")</span>
|
||||
}
|
||||
@if (minutes > 0)
|
||||
{
|
||||
<span>@minutes minute@(minutes != 1 ? "s" : "")</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.Location))
|
||||
{
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-sm-4 text-muted">Location:</div>
|
||||
<div class="col-sm-8">
|
||||
<i class="bi bi-geo-alt"></i> @Model.Location
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actual Times (if recorded) -->
|
||||
@if (Model.ActualStartTime.HasValue || Model.ActualEndTime.HasValue)
|
||||
{
|
||||
<div class="card">
|
||||
<div class="card-header bg-info text-white">
|
||||
<h5 class="mb-0"><i class="bi bi-clock-history me-2"></i>Actual Times</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (Model.ActualStartTime.HasValue)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-4 text-muted">Arrived:</div>
|
||||
<div class="col-sm-8">@Model.ActualStartTime.Value.ToString("h:mm tt")</div>
|
||||
</div>
|
||||
}
|
||||
@if (Model.ActualEndTime.HasValue)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-4 text-muted">Completed:</div>
|
||||
<div class="col-sm-8">@Model.ActualEndTime.Value.ToString("h:mm tt")</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Right Column - Appointment Details -->
|
||||
<div class="col-lg-6">
|
||||
<!-- Appointment Information -->
|
||||
<div class="card mb-3">
|
||||
<div class="card-header bg-secondary text-white">
|
||||
<h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Appointment Details</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-4 text-muted">Type:</div>
|
||||
<div class="col-sm-8">
|
||||
<span class="badge bg-@Model.TypeColorClass">
|
||||
@if (!string.IsNullOrEmpty(Model.TypeIconClass))
|
||||
{
|
||||
<i class="@Model.TypeIconClass me-1"></i>
|
||||
}
|
||||
@Model.TypeDisplayName
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-4 text-muted">Status:</div>
|
||||
<div class="col-sm-8">
|
||||
<span class="badge bg-@Model.StatusColorClass">
|
||||
@if (!string.IsNullOrEmpty(Model.StatusIconClass))
|
||||
{
|
||||
<i class="@Model.StatusIconClass me-1"></i>
|
||||
}
|
||||
@Model.StatusDisplayName
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.JobId.HasValue)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-4 text-muted">Linked Job:</div>
|
||||
<div class="col-sm-8">
|
||||
<a asp-controller="Jobs" asp-action="Details" asp-route-id="@Model.JobId">
|
||||
@Model.JobNumber
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.AssignedWorkerName))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-4 text-muted">Assigned To:</div>
|
||||
<div class="col-sm-8">
|
||||
<span class="badge bg-info">
|
||||
<i class="bi bi-person"></i> @Model.AssignedWorkerName
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Description & Notes -->
|
||||
@if (!string.IsNullOrEmpty(Model.Description) || !string.IsNullOrEmpty(Model.Notes))
|
||||
{
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0"><i class="bi bi-file-text me-2"></i>Description & Notes</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (!string.IsNullOrEmpty(Model.Description))
|
||||
{
|
||||
<div class="mb-3">
|
||||
<strong>Description:</strong>
|
||||
<p class="mb-0 mt-1">@Model.Description</p>
|
||||
</div>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.Notes))
|
||||
{
|
||||
<div>
|
||||
<strong>Internal Notes:</strong>
|
||||
<p class="mb-0 mt-1 text-muted">@Model.Notes</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Reminder Settings -->
|
||||
@if (Model.IsReminderEnabled)
|
||||
{
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0"><i class="bi bi-bell me-2"></i>Reminder</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 text-muted">Reminder:</div>
|
||||
<div class="col-sm-8">
|
||||
<i class="bi bi-check-circle text-success"></i>
|
||||
@Model.ReminderMinutesBefore minutes before
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Audit Information -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0"><i class="bi bi-clock-history me-2"></i>History</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-4 text-muted">Created:</div>
|
||||
<div class="col-sm-8">
|
||||
@Model.CreatedAt.ToString("MMM dd, yyyy h:mm tt")
|
||||
@if (!string.IsNullOrEmpty(Model.CreatedBy))
|
||||
{
|
||||
<br /><small class="text-muted">by @Model.CreatedBy</small>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="card mt-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>
|
||||
<a asp-action="Edit" asp-route-id="@Model.Id" class="btn btn-primary">
|
||||
<i class="bi bi-pencil"></i> Edit Appointment
|
||||
</a>
|
||||
<a asp-action="Calendar" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-calendar3"></i> View Calendar
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-outline-danger" onclick="deleteAppointment(@Model.Id, '@Model.AppointmentNumber')">
|
||||
<i class="bi bi-trash"></i> Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<script>
|
||||
function deleteAppointment(id, appointmentNumber) {
|
||||
if (confirm(`Are you sure you want to delete appointment ${appointmentNumber}?\n\nThis action cannot be undone.`)) {
|
||||
const form = document.createElement('form');
|
||||
form.method = 'POST';
|
||||
form.action = '@Url.Action("Delete")';
|
||||
|
||||
const idInput = document.createElement('input');
|
||||
idInput.type = 'hidden';
|
||||
idInput.name = 'id';
|
||||
idInput.value = id;
|
||||
form.appendChild(idInput);
|
||||
|
||||
const tokenInput = document.createElement('input');
|
||||
tokenInput.type = 'hidden';
|
||||
tokenInput.name = '__RequestVerificationToken';
|
||||
tokenInput.value = '@Html.AntiForgeryToken()'.match(/value="([^"]+)"/)[1];
|
||||
form.appendChild(tokenInput);
|
||||
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
}
|
||||
Reference in New Issue
Block a user