Skip to content

Commit 3ac3b13

Browse files
authored
loooot
1 parent 677ad1e commit 3ac3b13

2 files changed

Lines changed: 180 additions & 12 deletions

File tree

index.html

Lines changed: 151 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
border: 1px solid var(--color-gold-border) !important;
9595
color: var(--color-parchment) !important;
9696
}
97-
#json-input { background-color: rgba(10, 20, 15, 0.7) !important; border: 1px solid var(--color-gold-border) !important; color: #a0aec0 !important; }
97+
#json-input, #loot-json-input { background-color: rgba(10, 20, 15, 0.7) !important; border: 1px solid var(--color-gold-border) !important; color: #a0aec0 !important; }
9898

9999
#background-video { position: fixed; right: 0; bottom: 0; min-width: 100%; min-height: 100%; z-index: -100; object-fit: cover; filter: brightness(0.4); }
100100
.content-wrapper { position: relative; z-index: 2; }
@@ -326,11 +326,14 @@ <h3>Gildenrat-Login</h3>
326326
let currentRosterUnsubscribe = null;
327327
let historyUnsubscribe = null;
328328
let assignmentUnsubscribe = null;
329+
let lootDatesUnsubscribe = null;
330+
let selectedLootDateUnsubscribe = null;
329331
let heartbeatIntervalId = null;
330332

331333
const DATA_COLLECTION = "raid-tool-data";
332334
const HISTORY_COLLECTION = "raid-tool-history";
333335
const USER_PROFILES_COLLECTION = "user_profiles";
336+
const LOOT_COLLECTION = "raid-tool-loot";
334337

335338
const raidData = {
336339
mogushan: {
@@ -408,6 +411,7 @@ <h3>Gildenrat-Login</h3>
408411
const rosterDocRef = doc(db, DATA_COLLECTION, "currentRoster");
409412
const historyCollectionRef = collection(db, HISTORY_COLLECTION);
410413
const userProfilesCollectionRef = collection(db, USER_PROFILES_COLLECTION);
414+
const lootCollectionRef = collection(db, LOOT_COLLECTION);
411415

412416
// ============== MODAL-FUNKTION (global verfügbar) ==============
413417
window.showModal = function(message, isConfirm = false) {
@@ -599,7 +603,8 @@ <h3>Nachricht</h3>
599603
const pageId = `${raidId}/${boss.id}`;
600604
navHTML += `<a href="#${pageId}" data-page-id="${pageId}" class="nav-link hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-md transition-colors duration-200">${boss.name}</a>`;
601605
});
602-
606+
607+
navHTML += `<a href="#loot" data-page-id="loot" class="nav-link text-white font-bold py-2 px-4 rounded-md transition-colors duration-200" style="background-color: #7c3aed; border-color: transparent;">Loot</a>`;
603608
navHTML += `<a href="#history" data-page-id="history" class="nav-link bg-indigo-600 hover:bg-indigo-500 text-white font-bold py-2 px-4 rounded-md transition-colors duration-200">Änderungsverlauf</a>`;
604609
bossNav.innerHTML = navHTML;
605610
}
@@ -608,6 +613,8 @@ <h3>Nachricht</h3>
608613
if (currentRosterUnsubscribe) { currentRosterUnsubscribe(); currentRosterUnsubscribe = null; }
609614
if (historyUnsubscribe) { historyUnsubscribe(); historyUnsubscribe = null; }
610615
if (assignmentUnsubscribe) { assignmentUnsubscribe(); assignmentUnsubscribe = null; }
616+
if (lootDatesUnsubscribe) { lootDatesUnsubscribe(); lootDatesUnsubscribe = null; }
617+
if (selectedLootDateUnsubscribe) { selectedLootDateUnsubscribe(); selectedLootDateUnsubscribe = null; }
611618

612619
const filePath = pageId.includes('/') ? `${pageId}.html` : `${pageId}.html`;
613620

@@ -648,11 +655,6 @@ <h3>Nachricht</h3>
648655
setupAuthUI();
649656

650657
raidSelector.addEventListener('change', () => {
651-
// ++ KORRIGIERTE LOGIK ++
652-
// Wenn der User den Raid wechselt, soll zur #comp Seite navigiert werden.
653-
// Wenn wir schon auf #comp sind, würde das `hashchange` Event nicht feuern.
654-
// Deshalb rufen wir in diesem Fall die Render-Funktion manuell auf.
655-
// Andernfalls setzen wir den Hash, was das Event automatisch auslöst.
656658
if (window.location.hash === '#comp' || window.location.hash === '') {
657659
renderCurrentState();
658660
} else {
@@ -662,7 +664,6 @@ <h3>Nachricht</h3>
662664

663665
window.addEventListener('hashchange', renderCurrentState);
664666

665-
// Initialer Seitenaufbau
666667
renderCurrentState();
667668
});
668669

@@ -683,9 +684,10 @@ <h3>Nachricht</h3>
683684
initCompPage();
684685
} else if (pageId === 'history') {
685686
initHistoryPage();
687+
} else if (pageId === 'loot') {
688+
initLootPage();
686689
} else if (pageId === 'impressum' || pageId === 'datenschutz') {
687-
// Für diese einfachen Text-Seiten ist keine weitere Javascript-Aktion nötig.
688-
// Der Inhalt wurde bereits geladen, wir sind hier fertig.
690+
// No JS needed
689691
} else {
690692
initBossPage(pageId);
691693
}
@@ -731,6 +733,144 @@ <h3>Nachricht</h3>
731733
});
732734
});
733735
}
736+
737+
// --- Logik für loot.html ---
738+
function initLootPage() {
739+
const importSection = document.getElementById('loot-import-section');
740+
const importBtn = document.getElementById('import-loot-btn');
741+
742+
if (window.isManager) {
743+
importSection.style.display = 'block';
744+
importBtn?.addEventListener('click', handleLootImport);
745+
}
746+
747+
const q = query(lootCollectionRef, orderBy("raidDate", "desc"));
748+
lootDatesUnsubscribe = onSnapshot(q, (snapshot) => {
749+
const datesList = document.getElementById('loot-dates-list');
750+
if (!datesList) return;
751+
752+
if (snapshot.empty) {
753+
datesList.innerHTML = '<p class="text-gray-500">Keine Loot-Daten gefunden.</p>';
754+
return;
755+
}
756+
757+
datesList.innerHTML = '';
758+
snapshot.forEach(doc => {
759+
const date = doc.id;
760+
const dateButton = document.createElement('button');
761+
dateButton.className = 'w-full text-left p-2 rounded-md nav-link';
762+
dateButton.textContent = new Date(date + 'T12:00:00Z').toLocaleDateString('de-DE', { year: 'numeric', month: 'long', day: 'numeric' });
763+
dateButton.dataset.dateId = date;
764+
dateButton.onclick = () => {
765+
document.querySelectorAll('#loot-dates-list button').forEach(btn => btn.classList.remove('active-tab'));
766+
dateButton.classList.add('active-tab');
767+
displayLootForDate(date);
768+
};
769+
datesList.appendChild(dateButton);
770+
});
771+
});
772+
}
773+
774+
async function handleLootImport() {
775+
if (!window.isManager) return;
776+
const jsonString = document.getElementById('loot-json-input').value;
777+
if (!jsonString) return window.showModal("Bitte JSON einfügen.");
778+
779+
try {
780+
const data = JSON.parse(jsonString);
781+
if (!Array.isArray(data) || data.length === 0) {
782+
throw new Error("JSON muss ein Array von Loot-Objekten sein und darf nicht leer sein.");
783+
}
784+
785+
const firstTimestamp = data[0].timestamp;
786+
if (!firstTimestamp) throw new Error("Erstes Objekt im JSON hat keinen 'timestamp'.");
787+
788+
const raidDate = new Date(firstTimestamp * 1000).toISOString().split('T')[0]; // Format: YYYY-MM-DD
789+
790+
const lootDocRef = doc(db, LOOT_COLLECTION, raidDate);
791+
await setDoc(lootDocRef, { lootData: data, raidDate: raidDate });
792+
793+
const currentManager = sessionStorage.getItem('currentManager') || 'Unbekannt';
794+
window.logHistory('Loot', `Importiert für ${raidDate}`, `${data.length} Items`, currentManager);
795+
window.showModal(`Loot für den ${new Date(raidDate + 'T12:00:00Z').toLocaleDateString('de-DE')} wurde erfolgreich importiert!`);
796+
document.getElementById('loot-json-input').value = '';
797+
798+
} catch (error) {
799+
window.showModal("Fehler beim Verarbeiten des JSON: " + error.message);
800+
console.error(error);
801+
}
802+
}
803+
804+
function displayLootForDate(dateId) {
805+
if (selectedLootDateUnsubscribe) {
806+
selectedLootDateUnsubscribe();
807+
}
808+
809+
const lootDocRef = doc(db, LOOT_COLLECTION, dateId);
810+
const displayContainer = document.getElementById('loot-details-display');
811+
displayContainer.innerHTML = '<p class="text-gray-400">Lade Loot-Daten...</p>';
812+
813+
selectedLootDateUnsubscribe = onSnapshot(lootDocRef, (docSnap) => {
814+
if (!docSnap.exists()) {
815+
displayContainer.innerHTML = '<p class="text-red-400">Fehler: Loot-Daten für dieses Datum nicht gefunden.</p>';
816+
return;
817+
}
818+
819+
const lootData = docSnap.data().lootData;
820+
lootData.sort((a, b) => a.timestamp - b.timestamp);
821+
822+
let html = '';
823+
lootData.forEach(item => {
824+
const awardedTo = item.awardedTo.split('-')[0];
825+
const winnerRoll = item.Rolls.find(r => r.player === awardedTo);
826+
const winnerClass = winnerRoll ? winnerRoll.class.toUpperCase() : 'UNKNOWN';
827+
const winnerColor = window.classColors[winnerClass] || '#FFFFFF';
828+
829+
const rollsHtml = item.Rolls
830+
.sort((a, b) => b.amount - a.amount)
831+
.map(roll => {
832+
const rollType = roll.classification;
833+
let maxRoll = 100;
834+
if (rollType === 'OS') maxRoll = 50;
835+
else if (rollType === 'T-Mog') maxRoll = 25;
836+
837+
const playerColor = window.classColors[roll.class.toUpperCase()] || '#FFFFFF';
838+
const isWinner = roll.player === awardedTo;
839+
const fontWeight = isWinner ? 'font-bold text-lg' : 'font-normal';
840+
const rollColor = isWinner ? 'text-yellow-400' : 'text-gray-300';
841+
842+
return `<span class="whitespace-nowrap ${fontWeight}"><span style="color:${playerColor}">${roll.player}</span>: <span class="${rollColor}">${roll.amount}</span> <span class="text-xs text-gray-500">(${rollType}/${maxRoll})</span></span>`;
843+
}).join('&nbsp; ');
844+
845+
// --- NEU: Wowhead-Link erstellen ---
846+
// Item-Namen aus "[Item Name]" extrahieren
847+
const itemName = item.itemLink.replace(/[\[\]]/g, '');
848+
// Wowhead-URL für MoP Classic zusammenbauen
849+
const wowheadUrl = `https://www.wowhead.com/mop-classic/item=${item.itemID}`;
850+
// Das komplette <a>-Tag für den Link erstellen
851+
const itemLinkHtml = `<a href="${wowheadUrl}" target="_blank" rel="noopener noreferrer" class="hover:underline">${itemName}</a>`;
852+
// --- Ende der neuen Sektion ---
853+
854+
html += `
855+
<div class="bg-slate-750 p-4 rounded-lg mb-4">
856+
<div class="flex justify-between items-start">
857+
<h4 class="text-lg font-bold" style="color: var(--color-gold);">${itemLinkHtml}</h4>
858+
<span class="text-sm text-gray-400">${new Date(item.timestamp * 1000).toLocaleTimeString('de-DE')}</span>
859+
</div>
860+
<p class="mt-1">Vergeben an: <strong style="color: ${winnerColor};">${awardedTo}</strong></p>
861+
<div class="mt-2 text-sm">
862+
<p class="font-semibold">Würfe:</p>
863+
<div class="flex flex-wrap gap-x-4 gap-y-1 mt-1">
864+
${rollsHtml}
865+
</div>
866+
</div>
867+
</div>
868+
`;
869+
});
870+
871+
displayContainer.innerHTML = html || '<p>Keine Items für dieses Datum gefunden.</p>';
872+
});
873+
}
734874

735875
// --- Logik für Boss-Seiten ---
736876
function initBossPage(pageId) {
@@ -835,7 +975,6 @@ <h3>Nachricht</h3>
835975

836976
function createPlayerElement(player) {
837977
const playerDiv = document.createElement('div');
838-
// Die Klasse für die responsive Anpassung bleibt erhalten
839978
playerDiv.className = 'flex justify-between items-center player-row-container';
840979
playerDiv.dataset.playerId = player.id;
841980

@@ -881,7 +1020,7 @@ <h3>Nachricht</h3>
8811020
nameInput?.addEventListener('keydown', (event) => {
8821021
if (event.key === 'Enter') {
8831022
event.preventDefault();
884-
event.target.blur(); // Simuliert das Verlassen des Feldes
1023+
event.target.blur();
8851024
}
8861025
});
8871026
const classSelect = element.querySelector('.editable-class-select');

loot.html

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<main class="space-y-6">
2+
<h1 class="text-3xl font-bold text-center text-blue-450 mb-6">Loot-Verlauf</h1>
3+
4+
<section id="loot-import-section" class="bg-slate-850 p-6 rounded-lg" style="display: none;">
5+
<h3 class="text-xl font-semibold mb-3 text-blue-450">Loot-Daten Importieren</h3>
6+
<p class="text-gray-400 mb-4">Nur Gildenräte können neue Loot-Daten importieren. Füge den JSON-String aus dem Addon hier ein.</p>
7+
<textarea id="loot-json-input" class="w-full h-32 bg-slate-900 text-gray-300 p-3 rounded-md border border-slate-650 focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="[{...},{...}]"></textarea>
8+
<div class="flex flex-wrap gap-4 mt-4">
9+
<button id="import-loot-btn" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-6 rounded-md transition-colors duration-200">
10+
Loot importieren
11+
</button>
12+
</div>
13+
</section>
14+
15+
<div class="flex flex-col md:flex-row gap-6">
16+
<aside class="w-full md:w-1/4 bg-slate-850 p-4 rounded-lg">
17+
<h4 class="text-lg font-bold mb-3 border-b border-slate-650 pb-2">Raid-Datum</h4>
18+
<div id="loot-dates-list" class="space-y-2">
19+
<p class="text-gray-500">Keine Loot-Daten gefunden.</p>
20+
</div>
21+
</aside>
22+
23+
<section id="loot-details-container" class="w-full md:w-3/4 bg-slate-850 p-6 rounded-lg">
24+
<div id="loot-details-display">
25+
<p class="text-gray-400">Bitte wähle links ein Datum aus, um die Loot-Verteilung anzuzeigen.</p>
26+
</div>
27+
</section>
28+
</div>
29+
</main>

0 commit comments

Comments
 (0)