You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
6.8 KiB
Plaintext

@page "/{recordType}/{territoryId}"
@model Expedience.Web.Pages.RecordsModel
@{
ViewData["Title"] = "Expedience";
var roleOrder = new Dictionary<string, int>
{
{"Tank", 0},
{"Healer", 1},
{"DPS", 2}
};
var jobRoles = new Dictionary<string, string>
{
{"MRD", "Tank"}, {"GLA", "Tank"}, {"PLD", "Tank"}, {"GNB", "Tank"}, {"DRK", "Tank"}, {"WAR", "Tank"},
{"CNJ", "Healer"}, {"SCH", "Healer"}, {"SGE", "Healer"}, {"WHM", "Healer"}, {"AST", "Healer"}
};
Func<string, string> getRole = job => jobRoles.ContainsKey(job) ? jobRoles[job] : "DPS";
<style>
#topTenResultsTable {
width: 100%;
table-layout: fixed;
}
#topTenResultsTable th,
#topTenResultsTable td {
padding: 8px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#topTenResultsTable .expand-column {
width: 3%;
text-align: center;
}
#topTenResultsTable .rank-column {
width: 7%;
text-align: center;
}
#topTenResultsTable .player-column {
width: 25%;
}
#topTenResultsTable .job-column {
width: 7%;
text-align: center;
}
#topTenResultsTable .date-column {
width: 10%;
}
#topTenResultsTable .world-column {
width: 10%;
}
#topTenResultsTable .duration-column {
width: 10%;
}
#topTenResultsTable .rank-column,
#topTenResultsTable .job-column {
vertical-align: middle;
}
.expand-button {
background: none;
border: none;
color: white;
font-size: 1.2em;
cursor: pointer;
}
.duty-members-table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
.duty-members-table td {
padding: 0;
text-align: center;
vertical-align: middle;
}
.duty-members-table .member-icon {
width: 32px;
padding: 0;
line-height: 0;
}
.duty-members-table img {
display: block;
width: 32px;
height: 32px;
}
.duty-members-container {
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 5px 0;
}
.hidden {
display: none;
}
.duty-details {
font-size: 0.9em;
margin-left: 20px;
}
.duty-details p {
margin: 2px 0;
}
.duty-details strong {
font-weight: bold;
color: #aaa;
}
.duty-info-container {
display: flex;
align-items: flex-start;
padding: 5px 0;
}
.duty-members-container {
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 5px 0;
}
.duty-members-group {
display: flex;
flex-wrap: wrap;
margin-bottom: 2px;
}
.member-icon {
width: 32px;
height: 32px;
margin: 1px;
padding: 0;
display: block;
}
.player-icon {
box-shadow: 0 0 5px 3px rgba(255, 215, 0, 0.7);
border-radius: 50%;
}
.duty-details {
font-size: 0.9em;
padding-left: 8px;
}
.detail-row {
display: flex;
margin: 2px 0;
}
.detail-label {
font-weight: bold;
color: #aaa;
width: 100px; /* Adjust this value based on your longest label */
padding-right: 10px;
text-align: left;
}
.detail-value {
flex: 1;
text-align: left;
}
#topTenResultsTable td {
padding: 8px;
}
.duty-header {
font-size: 1.5em;
font-weight: bold;
margin-bottom: 20px;
color: #fff; /* Adjust color as needed */
text-align: center;
}
</style>
var dutyName = Model.Results.FirstOrDefault()?.Territory?.ContentName ?? "Unknown Duty";
<h2 class="duty-header">@dutyName - @Model.Mode</h2>
<table class="table table-dark table-striped" id="topTenResultsTable" data-toggle="table">
<thead>
<tr>
<th class="expand-column"></th>
<th class="rank-column" data-sortable="true">Rank</th>
<th class="player-column" data-sortable="true">Player</th>
<th class="job-column" data-sortable="true">Job</th>
<th class="duration-column" data-sortable="true" data-sorter="durationSorter">Duration</th>
<th class="date-column" data-sortable="true">Date</th>
<th class="world-column" data-sortable="true">Data Center</th>
</tr>
</thead>
<tbody>
@for (int i = 0; i < Math.Min(Model.Results.Count, 10); i++)
{
var result = Model.Results[i];
var playerMember = result.DutyMembers.FirstOrDefault(m => m.IsPlayer == true);
<tr>
<td>
<button class="expand-button" onclick="toggleDutyMembers(this, '@i')">+</button>
</td>
<td class="rank-column">@(i + 1)</td>
<td class="player-column">@result.User.UserName</td>
<td class="job-column">
@if (playerMember != null)
{
<img src="~/images/@(playerMember.ClassJob).png" alt="@playerMember.ClassJob" title="@playerMember.ClassJob" width="24" height="24" />
}
</td>
<td class="duration-column">@($"{result.Hours:D2}:{result.Minutes:D2}:{result.Seconds:D2}.{result.Milliseconds:D3}")</td>
<td class="date-column">@result.EndTime.ToString("yyyy-MM-dd")</td>
<td class="world-column">@result.DataCenter</td>
</tr>
<tr class="hidden" id="dutyMembers-@i">
<td></td>
<td></td>
<td>
<div class="duty-members-container">
@foreach (var group in result.DutyMembers.GroupBy(m => m.GroupNumber).OrderBy(g => g.Key))
{
<div class="duty-members-group">
@foreach (var member in group
.OrderBy(m => roleOrder[getRole(m.ClassJob)])
.ThenBy(m => m.ClassJob))
{
<img class="member-icon @(member.IsPlayer ? "player-icon" : "")"
src="~/images/@(member.ClassJob).png"
alt="@member.ClassJob"
title="@member.ClassJob" />
}
</div>
}
</div>
</td>
<td colspan="4">
<div class="duty-details">
<div class="detail-row">
<div class="detail-label">Start Time:</div>
<div class="detail-value">@result.StartTime.ToString("yyyy-MM-dd HH:mm:ss")</div>
</div>
<div class="detail-row">
<div class="detail-label">End Time:</div>
<div class="detail-value">@result.EndTime.ToString("yyyy-MM-dd HH:mm:ss")</div>
</div>
<div class="detail-row">
<div class="detail-label">Uploaded At:</div>
<div class="detail-value">@result.UploadedAt.ToString("yyyy-MM-dd HH:mm:ss")</div>
</div>
<div class="detail-row">
<div class="detail-label">Game Version:</div>
<div class="detail-value">@result.GameVersion</div>
</div>
<div class="detail-row">
<div class="detail-label">Plugin Version:</div>
<div class="detail-value">@result.PluginVersion</div>
</div>
</div>
</td>
</tr>
}
</tbody>
</table>
<br />
<a href="javascript:history.back()">Go Back</a>
<script>
function toggleDutyMembers(button, index) {
var row = document.getElementById('dutyMembers-' + index);
if (row.style.display === 'none' || row.style.display === '') {
row.style.display = 'table-row';
button.textContent = '-';
} else {
row.style.display = 'none';
button.textContent = '+';
}
}
</script>
}