Display CostItemViewModel Headers in Table

Answered using OpenAI o1 mini by OpenAI o1

Question:

у меня есть представление

@using Microsoft.AspNetCore.Mvc.TagHelpers
@model BuildingFlow.Services.Models.ViewModels.ProjectStage.ProjectStageViewModel

@{
    ViewData["Title"] = "Index";
    ViewData["statusClass"] = "";
}

@section VendorStyles {
    <link rel="stylesheet" href="~/vendor/libs/datatables-bs5/datatables.bootstrap5.css">
    <link rel="stylesheet" href="~/vendor/libs/datatables-responsive-bs5/responsive.bootstrap5.css">
    <link rel="stylesheet" href="~/vendor/libs/datatables-buttons-bs5/buttons.bootstrap5.css">
    <link rel="stylesheet" href="~/vendor/libs/sweetalert2/sweetalert2.css" />
    <link rel="stylesheet" href="~/vendor/libs/&#64;form-validation/form-validation.css" />
}

@section VendorScripts {
    <script src="~/vendor/libs/moment/moment.js"></script>
    <script src="~/vendor/libs/datatables-bs5/datatables-bootstrap5.js"></script>
    <script src="~/vendor/libs/sweetalert2/sweetalert2.js"></script>
    <script src="~/vendor/libs/&#64;form-validation/popular.js"></script>
    <script src="~/vendor/libs/&#64;form-validation/bootstrap5.js"></script>
    <script src="~/vendor/libs/&#64;form-validation/auto-focus.js"></script>
    <script src="~/vendor/libs/cleavejs/cleave.js"></script>
    <script src="~/vendor/libs/cleavejs/cleave-phone.js"></script>
}

@section PageScripts {
    <script src="~/js/_buildingFlow-costitem-list.js"></script>
}

<div class="row g-6 mb-6">
  <div class="col-sm-6 col-xl-3">
    <div class="card">
      <div class="card-body">
        <div class="d-flex align-items-start justify-content-between">
          <div class="content-left">
            <div class="d-flex align-items-center my-1">
              <h4 class="mb-0 me-2">155</h4>
              <p class="text-primary mb-0"></p>
            </div>
            <small class="mb-0">Total Transactions</small>
          </div>
          <div class="avatar">
            <span class="avatar-initial rounded bg-label-primary">
              <i class="bx bx-transfer-alt bx-lg"></i>
            </span>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="col-sm-6 col-xl-3">
    <div class="card">
      <div class="card-body">
        <div class="d-flex align-items-start justify-content-between">
          <div class="content-left">
            <div class="d-flex align-items-center my-1">
              <h4 class="mb-0 me-2">$12555</h4>
              <p class="text-success mb-0"></p>
            </div>
            <small class="mb-0">Total Paid</small>
          </div>
          <div class="avatar">
            <span class="avatar-initial rounded bg-label-success">
              <i class="bx bx-user-check bx-lg"></i>
            </span>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="col-sm-6 col-xl-3">
    <div class="card">
      <div class="card-body">
        <div class="d-flex align-items-start justify-content-between">
          <div class="content-left">
            <div class="d-flex align-items-center my-1">
              <h4 class="mb-0 me-2">$35544</h4>
              <p class="text-danger mb-0"></p>
            </div>
            <small class="mb-0">Total Due</small>
          </div>
          <div class="avatar">
            <span class="avatar-initial rounded bg-label-danger">
              <i class="bx bx-group bx-lg"></i>
            </span>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="col-sm-6 col-xl-3">
    <div class="card">
      <div class="card-body">
        <div class="d-flex align-items-start justify-content-between">
          <div class="content-left">
            <div class="d-flex align-items-center my-1">
              <h4 class="mb-0 me-2">$55587</h4>
              <p class="text-success mb-0"></p>
            </div>
            <small class="mb-0">Total Canceled</small>
          </div>
          <div class="avatar">
            <span class="avatar-initial rounded bg-label-warning">
              <i class="bx bx-user-voice bx-lg"></i>
            </span>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

@* CostItems Table *@
<div class="card">
    <div class="card-datatable table-responsive pb-0">
        <table id="costItemsTable" class="table mb-6">
            <thead class="border-top">
                <tr class="text-nowrap">
                    <th></th>
                    <th>@Html.DisplayNameFor(model => model.Id)</th>
                    <th>
                        @Html.DisplayNameFor(model => model.Customer)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.TransactionDate)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.DueDate)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Total)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Status)
                    </th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                @if (Model?.Any() == true)
                {
                    @foreach (var item in Model)
                    {
                        string statusClass = "info"; // Default value if item.Status is null or doesn't match any case

                        if (!string.IsNullOrWhiteSpace(item.Status))
                        {
                            string lowerCaseStatus = item.Status.ToLower();

                            if (lowerCaseStatus == "paid")
                            {
                                statusClass = "success";
                            }
                            else if (lowerCaseStatus == "due")
                            {
                                statusClass = "warning";
                            }
                            else if (lowerCaseStatus == "canceled")
                            {
                                statusClass = "danger";
                            }
                        }

                        <tr>
                            <td></td>
                            <td>
                                @Html.DisplayFor(modelItem => item.Id)
                            </td>
                            <td class="text-nowrap fw-medium text-heading">
                                @Html.DisplayFor(modelItem => item.Customer)
                            </td>
                            <td>
                                @item.TransactionDate.ToString("dd.MM.yyyy")
                            </td>
                            <td>
                                @item.DueDate.ToString("dd.MM.yyyy")
                            </td>
                            <td>
                                [email protected]
                            </td>
                            <td>
                                <div class="badge bg-label-@statusClass rounded-pill">
                                    @Html.DisplayFor(modelItem => item.Status)
                                </div>
                            </td>
                            <td class="text-nowrap">
                                <a asp-action="Update" asp-route-id="@item.Id" class="btn btn-sm btn-icon shadow-none"><i class='bx bx-edit'></i></a>
                                <a href="/Transactions/Delete/@item.Id" class="btn btn-sm btn-icon shadow-none delete-transaction" data-transaction-username="@Html.DisplayFor(modelItem => item.Customer)"><i class="bx bx-trash"></i></a>
                            </td>
                        </tr>
                    }
                }
            </tbody>
        </table>
    </div>
</div>
и есть модель
public class ProjectStageViewModel
{
    public int Id { get; set; }

    [Required(ErrorMessage = "Название этапа обязательно")]
    [StringLength(200, ErrorMessage = "Название этапа не должно превышать 200 символов")]
    [Display(Name = "Название этапа")]
    public string StageTitle { get; set; }

    [StringLength(1000, ErrorMessage = "Описание не должно превышать 1000 символов")]
    [Display(Name = "Описание")]
    public string Description { get; set; }

    [Display(Name = "Дата начала")]
    [DataType(DataType.Date)]
    public DateTime StartDate { get; set; }

    [Display(Name = "Дата окончания")]
    [DataType(DataType.Date)]
    public DateTime EndDate { get; set; }

    [StringLength(50, ErrorMessage = "Статус не должен превышать 50 символов")]
    [Display(Name = "Статус")]
    public string Status { get; set; }

    [Required]
    public int ProjectId { get; set; }

    public IEnumerable<CostItemViewModel> CostItemViewModel { get; set; } = null;
    public SelectProjectViewModel SelectProjectViewModel { get; set; } = new SelectProjectViewModel();

    //[Display(Name = "Проект")]
    //[ValidateNever]
    //public string ProjectName { get; set; } // Дополнительное свойство для отображения названия проекта
}
как в представлении в таблице отобразить заголовки CostItemViewModel?
Answer:

Чтобы отобразить заголовки CostItemViewModel в таблице вашего представления, вам нужно сначала убедиться, что у вас есть доступ к свойствам CostItemViewModel в вашем ProjectStageViewModel. Затем вы можете добавить соответствующие заголовки в таблицу.

Предположим, что CostItemViewModel имеет следующие свойства:

public class CostItemViewModel
{
    public int Id { get; set; }
    public string Customer { get; set; }
    public DateTime TransactionDate { get; set; }
    public DateTime DueDate { get; set; }
    public decimal Total { get; set; }
    public string Status { get; set; }
}

Теперь вы можете обновить ваше представление, чтобы добавить заголовки для свойств CostItemViewModel в таблицу. Вот как это можно сделать:

  1. Добавьте заголовки для свойств CostItemViewModel в секцию <thead> таблицы.
  2. В секции <tbody> добавьте строки для каждого элемента CostItemViewModel.

Вот пример, как это может выглядеть:

@* CostItems Table *@
<div class="card">
    <div class="card-datatable table-responsive pb-0">
        <table id="costItemsTable" class="table mb-6">
            <thead class="border-top">
                <tr class="text-nowrap">
                    <th></th>
                    <th>@Html.DisplayNameFor(model => model.Id)</th>
                    <th>@Html.DisplayNameFor(model => model.StageTitle)</th> <!-- Заголовок для StageTitle -->
                    <th>@Html.DisplayNameFor(model => model.StartDate)</th> <!-- Заголовок для StartDate -->
                    <th>@Html.DisplayNameFor(model => model.EndDate)</th> <!-- Заголовок для EndDate -->
                    <th>@Html.DisplayNameFor(model => model.Status)</th> <!-- Заголовок для Status -->
                    <th>Cost Items</th> <!-- Заголовок для Cost Items -->
                </tr>
                <tr class="text-nowrap">
                    <th></th>
                    <th>@Html.DisplayNameFor(model => model.CostItemViewModel.First().Id)</th>
                    <th>@Html.DisplayNameFor(model => model.CostItemViewModel.First().Customer)</th>
                    <th>@Html.DisplayNameFor(model => model.CostItemViewModel.First().TransactionDate)</th>
                    <th>@Html.DisplayNameFor(model => model.CostItemViewModel.First().DueDate)</th>
                    <th>@Html.DisplayNameFor(model => model.CostItemViewModel.First().Total)</th>
                    <th>@Html.DisplayNameFor(model => model.CostItemViewModel.First().Status)</th>
                </tr>
            </thead>
            <tbody>
                @if (Model?.CostItemViewModel?.Any() == true)
                {
                    foreach (var costItem in Model.CostItemViewModel)
                    {
                        <tr>
                            <td></td>
                            <td>@Html.DisplayFor(modelItem => costItem.Id)</td>
                            <td class="text-nowrap fw-medium text-heading">@Html.DisplayFor(modelItem => costItem.Customer)</td>
                            <td>@costItem.TransactionDate.ToString("dd.MM.yyyy")</td>
                            <td>@costItem.DueDate.ToString("dd.MM.yyyy")</td>
                            <td>[email protected]</td>
                            <td>
                                <div class="badge [email protected]() rounded-pill">
                                    @Html.DisplayFor(modelItem => costItem.Status)
                                </div>
                            </td>
                        </tr>
                    }
                }
            </tbody>
        </table>
    </div>
</div>

Объяснение изменений:

  1. Заголовки: Я добавил заголовки для свойств CostItemViewModel в таблицу. Это позволяет пользователю видеть, какие данные будут отображены в строках таблицы.
  2. Строки таблицы: Внутри <tbody> я добавил цикл foreach, который проходит по каждому элементу CostItemViewModel и создает строки таблицы с соответствующими данными.

Убедитесь, что у вас есть данные в CostItemViewModel, чтобы они отображались в таблице.