feat: improve route list design and functionallity

This commit is contained in:
cuqmbr 2022-03-30 19:21:32 +03:00
parent 1b3b598539
commit 1146093913
5 changed files with 222 additions and 40 deletions

View File

@ -1,13 +1,16 @@
@page
@using System.Globalization
@using Newtonsoft.Json
@model TicketOffice.Pages.IndexModel
@{
ViewData["Title"] = "Home page";
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("uk-UA");
}
<link rel="stylesheet" href="~/css/Routes.css" asp-append-version="true"/>
<form class="search-block">
<div class="stations">
<div class="opt">
<div class="station">
<div class="title">
Звідки
@ -21,20 +24,22 @@
</div>
<input type="text" autocomplete="off" asp-for="to">
</div>
</div>
<div class="opt">
<div class="date">
<div class="title">
Дата відправлення
</div>
<input type="date" value="@Model.date.ToString("yyyy-MM-dd")" asp-for="date">
</div>
<div class="search-btn">
<input type="submit" class="search-btn" value="Пошук"/>
</div>
</div>
<input type="submit" value="Пошук"/>
</form>
<!--
<a asp-page-handler="SortByDuration" asp-route-from=@Model.from a in a asp-route-to=@Model.to asp-route-date=@Model.date.ToString("yyyy-MM-dd") asp-route-isDescending="false">За зростанням</a>
<a asp-page-handler="SortByDuration" asp-route-from=@Model.from a in a asp-route-to=@Model.to asp-route-date=@Model.date.ToString("yyyy-MM-dd") asp-route-isDescending="true">За спаданням</a>
-->
@if (Model.Route.Count > 0)
{
@ -44,6 +49,7 @@
<tr>
<th>
№ автобуса
<a class="link-btn-sort" asp-page-handler="SortByNumber" asp-route-from=@Model.from a in a asp-route-to=@Model.to asp-route-date=@Model.date.ToString("yyyy-MM-dd")>🠕</a>
</th>
<th>
Звідки / Куди
@ -52,11 +58,18 @@
Дата
</th>
<th>
<div class="departure">Відправлення</div>
<div class="arrival">Прибуття</div>
<div class="departure">
Відправлення
<a class="link-btn-sort" asp-page-handler="SortByDeparture" asp-route-from=@Model.from a in a asp-route-to=@Model.to asp-route-date=@Model.date.ToString("yyyy-MM-dd")>🠕</a>
</div>
<div class="arrival">
Прибуття
<a class="link-btn-sort" asp-page-handler="SortByArrival" asp-route-from=@Model.from a in a asp-route-to=@Model.to asp-route-date=@Model.date.ToString("yyyy-MM-dd")>🠕</a>
</div>
</th>
<th>
Тривалість
<a class="link-btn-sort" asp-page-handler="SortByDuration" asp-route-from=@Model.from a in a asp-route-to=@Model.to asp-route-date=@Model.date.ToString("yyyy-MM-dd")>🠕</a>
</th>
<th>
Вільніих місць
@ -71,7 +84,8 @@
{
<tr class="table-row">
<td class="num">
@route.Number
<div>@route.Number</div>
<div class="city-list-btn"><a class="city-list-btn">Маршрут</a></div>
</td>
<td class="city">
<div>@route.Cities.First().Name</div>
@ -79,12 +93,20 @@
</td>
<td>
<div class="route-date">
<span>Відправлення</span>
<span>@route.Cities.First().DepartureTime?.ToString("dd.MM.yyy")</span>
<span>
Відправлення
</span>
<span>
@route.Cities.First().ArrivalTime?.ToString("f").Split(",")[0].ToLower(),
@route.Cities.First().DepartureTime?.ToString("dd.MM.yyyy")
</span>
</div>
<div class="route-date">
<span>Прибуття</span>
<span>@route.Cities.Last().ArrivalTime?.ToString("dd.MM.yyy")</span>
<span>
@route.Cities.Last().ArrivalTime?.ToString("f").Split(",")[0].ToLower(),
@route.Cities.Last().ArrivalTime?.ToString("dd.MM.yyyy")
</span>
</div>
</td>
<td class="time">
@ -93,13 +115,13 @@
</td>
<td class="duration">
@{ TimeSpan? duration = route.Cities.Last().ArrivalTime - route.Cities.First().DepartureTime; }
@($"{duration?.TotalHours.ToString().Split(".")[0]}:{duration?.Minutes}")
@($"{duration?.TotalHours.ToString().Split(",")[0]}:{duration?.Minutes}")
</td>
<td class="capacity">
@(route.Capacity - route.Tickets.Count)
</td>
<td class="action">
<a asp-page=".">Вибрати</a>
<a class="link-btn-choose">Вибрати</a>
</td>
</tr>
}

View File

@ -1,6 +1,8 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using System.Globalization;
using Newtonsoft.Json;
using TicketOffice.Data;
using TicketOffice.Models;
using Route = TicketOffice.Models.Route;
@ -22,38 +24,95 @@ public class IndexModel : PageModel
[BindProperty(SupportsGet = true)] public string from { get; set; }
[BindProperty(SupportsGet = true)] public string to { get; set; }
[BindProperty(SupportsGet = true)] public DateTime date { get; set; } = new DateTime(2022, 03, 28, 0, 0, 0).Date;
[BindProperty(SupportsGet = true)] public string SortString { get; set; }
public void OnGet()
{
RetrieveAllRoutes();
if (!string.IsNullOrWhiteSpace(from))
{
FilterRoutesByFrom();
}
if (!string.IsNullOrWhiteSpace(to))
{
FilterRoutesByTo();
}
FilterRoutesByDate();
}
public void OnGetSortByNumber()
{
OnGet();
Route.Sort((x, y) => Math.Clamp(x.Number - y.Number, -1, 1));
}
public void OnGetSortByDeparture()
{
OnGet();
Route.Sort((x, y) => Math.Clamp((int)(x.Cities.First().DepartureTime - y.Cities.First().DepartureTime).Value.TotalMilliseconds, -1, 1));
}
public void OnGetSortByArrival()
{
OnGet();
Route.Sort((x, y) =>
{
TimeSpan? totalDuration = x.Cities.Last().ArrivalTime - y.Cities.Last().ArrivalTime;
return Math.Clamp((int)totalDuration.Value.TotalMilliseconds, -1, 1);
});
}
public void OnGetSortByDuration()
{
OnGet();
Route.Sort((x, y) =>
{
TimeSpan? xDuration = x.Cities.Last().ArrivalTime - x.Cities.First().DepartureTime;
TimeSpan? yDuration = y.Cities.Last().ArrivalTime - y.Cities.First().DepartureTime;
TimeSpan? totalDuration = xDuration - yDuration;
return Math.Clamp((int)totalDuration.Value.TotalMilliseconds, -1, 1);
});
}
private void RetrieveAllRoutes()
{
Route = _context.Route
.Include(r => r.Cities)
.Include(r => r.Tickets)
.ToList();
if (!string.IsNullOrWhiteSpace(from) && !string.IsNullOrWhiteSpace(to))
{
FilterRoutes();
}
}
public void OnGetSortByDuration(bool isDescending)
{
OnGet();
Route.Sort((x, y) => (isDescending ? -1 : 1) *
(x.Cities.Last().ArrivalTime - x.Cities.First().DepartureTime).Value
.CompareTo((y.Cities.Last().ArrivalTime - y.Cities.First().DepartureTime).Value) + 1);
}
private void FilterRoutes()
private void FilterRoutesByFrom()
{
Route.ForEach(r => r.Cities = r.Cities
.SkipWhile(c => c.Name != from).Reverse()
.SkipWhile(c => c.Name != to).Reverse()
.SkipWhile(c => c.Name != from)
.ToList());
Route.RemoveAll(r =>
r.Cities.Count < 2 || r.Cities.First().DepartureTime.Value.DayOfYear != date.DayOfYear);
Route.RemoveAll(r => r.Cities.Count < 2);
}
private void FilterRoutesByTo()
{
Route.ForEach(r => r.Cities = r.Cities
.Reverse().SkipWhile(c => c.Name != to)
.Reverse().ToList());
Route.RemoveAll(r => r.Cities.Count < 2);
}
private void FilterRoutesByDate()
{
Route.RemoveAll(r => r.Cities.First().DepartureTime.Value.DayOfYear != date.DayOfYear);
}
}

View File

@ -20,6 +20,64 @@ body {
margin: 0 auto;
}
.search-block {
background: #eaeef1;
box-shadow: 0 1px 2.4rem 0 #c3c9d0;
padding: 1.5rem 1.5rem 1.5rem 1.5rem;
margin: 1.5rem 0;
border-radius: 0.5rem;
}
.station, .date, div.search-btn {
display: inline-block;
margin: 0 1.5rem;
}
.title {
font-weight: 500;
color: #777a7e;
margin-bottom: .3rem;
}
input[type=text], input[type=date] {
font-size: 1.5rem;
color: #262626;
font-weight: 500;
line-height: 4.7rem;
width: 15rem;
height: 3rem;
box-sizing: border-box;
background: #dfe3e5;
border: 1px solid #b8bfc7;
box-shadow: 0 1px 0 0 #fff;
border-radius: .3rem;
padding: 0 1.1rem;
text-align: left;
}
input[type=text]:focus, input[type=date]:focus {
outline: 0;
border-color: #68b2dd;
background-color: #fff;
}
input.search-btn {
color: #1d4965;
font-size: 1.6rem;
font-weight: 700;
line-height: 3rem;
padding: 0 1.5rem;
display: inline-block;
background: linear-gradient(0deg,#79b6db,#b3dbf2);
border: none;
border-radius: .3rem;
cursor: pointer;
}
input.search-btn:hover {
opacity: 0.8;
}
.route-list {
margin-top: 3rem;
}
@ -45,8 +103,22 @@ th {
line-height: 1.6rem;
}
.link-btn-sort {
color: #777a7e;
text-decoration: none;
}
.link-btn-sort:hover {
color: #1d4965;
cursor: pointer;
}
.link-btn-sort:visited, .link-btn-sort:active {
text-decoration: none;
}
tr {
line-height: 6rem;
line-height: 5rem;
background-color: white;
}
@ -66,6 +138,23 @@ td.num, td.capacity {
line-height: 2rem;
}
.city-list-btn {
font-size: 0.8rem;
font-weight: 700;
line-height: 0.5rem;
color: #245c78;
text-decoration: none;
cursor: pointer;
}
.city-list-btn:visited {
text-decoration: none;
}
.city-list-btn:hover {
text-decoration: underline;
}
td.city {
font-size: 1rem;
font-weight: 700;
@ -75,28 +164,40 @@ td.city {
td.time, td.duration {
font-size: 1.2rem;
font-weight: 900;
line-height: 1.8rem;
line-height: 1.4rem;
}
.route-date {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #c5c7cc;
font-size: 0.75rem;
font-size: 0.7rem;
font-weight: 700;
line-height: 1.25rem;
}
.search-block {
background: #eaeef1;
box-shadow: 0 1px 2.4rem 0 #c3c9d0;
padding: 1.5rem 2.5rem 3.5rem 2.5rem;
.link-btn-choose {
line-height: 2.5rem;
padding: 0 1rem;
display: inline-block;
color: #1d4965;
font-weight: 500;
background: linear-gradient(0deg,#79b6db,#b3dbf2);
border: none;
border-radius: .3rem;
cursor: pointer;
text-decoration: none;
}
.link-btn-choose:hover {
opacity: 0.8;
}
.search-error {
background: #f1f2f4;
border: 1px solid #d7dce1;
box-shadow: 0 0 4px 0 rgba(195,201,208,.5);
font-weight: 700;
font-weight: 500;
font-size: 1.5rem;
padding: 4rem 4rem;
text-align: center;