Refactor and remove sqlite and replace with MySQL
This commit is contained in:
155
web/templates/account/tickets/add_ticket.html
Normal file
155
web/templates/account/tickets/add_ticket.html
Normal file
@@ -0,0 +1,155 @@
|
||||
{{ define "content" }}
|
||||
<a href="/">← Back</a>
|
||||
<h2>Log My Ticket</h2>
|
||||
|
||||
<form method="POST" action="/account/tickets/add_ticket" enctype="multipart/form-data" id="ticketForm">
|
||||
{{ .csrfField }}
|
||||
|
||||
<div class="form-section">
|
||||
<label>Game:
|
||||
<select name="game_type" id="gameType" required>
|
||||
<option value="">-- Select Game --</option>
|
||||
<option value="Thunderball" selected>Thunderball</option>
|
||||
<option value="Lotto">Lotto</option>
|
||||
<option value="EuroMillions">EuroMillions</option>
|
||||
<option value="SetForLife">Set For Life</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<label>Draw Date:
|
||||
<select name="draw_date" required>
|
||||
{{ range .DrawDates }}
|
||||
<option value="{{ . }}">{{ . }}</option>
|
||||
{{ else }}
|
||||
<option disabled>No draws available</option>
|
||||
{{ end }}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<label>Purchase Method:
|
||||
<select name="purchase_method" required>
|
||||
<option value="In-store">In-store</option>
|
||||
<option value="National-lottery.com">National-lottery.com</option>
|
||||
<option value="SynLotto">SynLotto</option>
|
||||
<option value="Other Online">Other Online</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<label for="purchase_date">Purchase Date:</label>
|
||||
<input type="date" name="purchase_date" id="purchase_date" required>
|
||||
|
||||
<label for="purchase_time">(Optional) Time:</label>
|
||||
<input type="time" name="purchase_time" id="purchase_time">
|
||||
</div>
|
||||
|
||||
<div id="ticketLinesContainer">
|
||||
<!-- JS will insert ticket lines here -->
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<label for="ticket_image">Upload Ticket Image (optional):</label>
|
||||
<input type="file" name="ticket_image" id="ticket_image" accept="image/*">
|
||||
</div>
|
||||
|
||||
<button type="button" onclick="addLine()">+ Add Line</button><br><br>
|
||||
<button type="submit">Save Ticket(s)</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
const gameConfig = {
|
||||
Thunderball: { balls: 5, bonus: 1, ballRange: [1, 39], bonusRange: [1, 14] },
|
||||
Lotto: { balls: 6, bonus: 0, ballRange: [1, 59], bonusRange: [] },
|
||||
EuroMillions: { balls: 5, bonus: 2, ballRange: [1, 50], bonusRange: [1, 12] },
|
||||
SetForLife: { balls: 5, bonus: 1, ballRange: [1, 47], bonusRange: [1, 10] }
|
||||
};
|
||||
|
||||
const container = document.getElementById("ticketLinesContainer");
|
||||
let lineCount = 0;
|
||||
|
||||
document.getElementById('gameType').addEventListener('change', () => {
|
||||
container.innerHTML = '';
|
||||
lineCount = 0;
|
||||
addLine();
|
||||
});
|
||||
|
||||
function addLine() {
|
||||
const game = document.getElementById("gameType").value;
|
||||
if (!game) {
|
||||
alert("Please select a game first.");
|
||||
return;
|
||||
}
|
||||
|
||||
const config = gameConfig[game];
|
||||
const lineId = `line-${lineCount++}`;
|
||||
const div = document.createElement('div');
|
||||
div.className = "ticket-line";
|
||||
div.style.marginBottom = "10px";
|
||||
|
||||
div.innerHTML = `
|
||||
<strong>Line ${lineCount}</strong><br>
|
||||
${Array.from({ length: 6 }, (_, i) => `
|
||||
<input type="number" name="ball${i+1}[]" ${i < config.balls ? '' : 'disabled'} required min="${config.ballRange[0]}" max="${config.ballRange[1]}" placeholder="Ball ${i+1}">
|
||||
`).join('')}
|
||||
${Array.from({ length: 2 }, (_, i) => `
|
||||
<input type="number" name="bonus${i+1}[]" ${i < config.bonus ? '' : 'disabled'} ${i < config.bonus ? 'required' : ''} min="${config.bonusRange[0] || 0}" max="${config.bonusRange[1] || 0}" placeholder="Bonus ${i+1}">
|
||||
`).join('')}
|
||||
`;
|
||||
container.appendChild(div);
|
||||
console.log(`🆕 Line ${lineCount} added for ${game}`);
|
||||
}
|
||||
|
||||
const form = document.getElementById('ticketForm');
|
||||
form.addEventListener('submit', function (e) {
|
||||
const lines = document.querySelectorAll(".ticket-line");
|
||||
if (lines.length === 0) {
|
||||
e.preventDefault();
|
||||
alert("Please select a game and add at least one line.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const line of lines) {
|
||||
const mainBalls = Array.from(line.querySelectorAll('input[name^="ball"]'))
|
||||
.filter(i => !i.disabled)
|
||||
.map(i => parseInt(i.value, 10));
|
||||
|
||||
const bonusBalls = Array.from(line.querySelectorAll('input[name^="bonus"]'))
|
||||
.filter(i => !i.disabled)
|
||||
.map(i => parseInt(i.value, 10));
|
||||
|
||||
const mainSet = new Set(mainBalls);
|
||||
const bonusSet = new Set(bonusBalls);
|
||||
|
||||
if (mainBalls.includes(NaN) || bonusBalls.includes(NaN)) {
|
||||
alert("All fields must be filled with valid numbers.");
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mainSet.size !== mainBalls.length) {
|
||||
alert("Duplicate main numbers detected.");
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (bonusSet.size !== bonusBalls.length) {
|
||||
alert("Duplicate bonus numbers detected.");
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const gameSelect = document.getElementById('gameType');
|
||||
if (gameSelect.value) {
|
||||
addLine();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{{ end }}
|
||||
92
web/templates/account/tickets/my_tickets.html
Normal file
92
web/templates/account/tickets/my_tickets.html
Normal file
@@ -0,0 +1,92 @@
|
||||
{{ define "content" }}
|
||||
<a href="/account/tickets/add_ticket">+ Add Ticket</a>
|
||||
<h2>My Tickets</h2>
|
||||
|
||||
{{ if eq (len .Tickets) 0 }}
|
||||
<p>You haven’t logged any tickets yet.</p>
|
||||
{{ else }}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Game</th>
|
||||
<th>Draw Date</th>
|
||||
<th>Numbers</th>
|
||||
<th>Bonus</th>
|
||||
<th>Purchased</th>
|
||||
<th>Via</th>
|
||||
<th>Image</th>
|
||||
<th>Prize</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range .Tickets }}
|
||||
{{ $ticket := . }}
|
||||
<tr>
|
||||
<td>{{ $ticket.GameType }}</td>
|
||||
<td>{{ $ticket.DrawDate }}</td>
|
||||
<td>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{{ range $i, $ball := $ticket.Balls }}
|
||||
<div class="ball game-{{lower $ticket.GameType}} {{ if eq $ticket.GameType "Lotto" }}lotto-range-{{rangeClass $ball}} {{ end }}{{ if inSlice $ball $ticket.MatchedDraw.Balls }}matched pulse{{ end }}">
|
||||
{{ $ball }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ if or (gt $ticket.MatchedMain 0) (gt $ticket.MatchedBonus 0) }}
|
||||
<div class="text-xs text-gray-500 mt-1">
|
||||
{{ $ticket.MatchedMain }} match{{ if ne $ticket.MatchedMain 1 }}es{{ end }}
|
||||
{{ if gt $ticket.MatchedBonus 0 }}, {{ $ticket.MatchedBonus }} bonus{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</td>
|
||||
<td>
|
||||
{{ if eq $ticket.GameType "Lotto" }}
|
||||
<span style="color: lightgray; font-style: italic;">–</span>
|
||||
{{ else if gt (intVal $ticket.Bonus2) 0 }}
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{{ if gt (intVal $ticket.Bonus1) 0 }}
|
||||
{{ $b1 := intVal $ticket.Bonus1 }}
|
||||
<div class="ball game-{{lower $ticket.GameType}} bonus{{ if inSlice $b1 $ticket.MatchedDraw.BonusBalls }} matched-bonus{{ end }}">
|
||||
{{ $b1 }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ $b2 := intVal $ticket.Bonus2 }}
|
||||
<div class="ball game-{{lower $ticket.GameType}} bonus{{ if inSlice $b2 $ticket.MatchedDraw.BonusBalls }} matched-bonus{{ end }}">
|
||||
{{ $b2 }}
|
||||
</div>
|
||||
</div>
|
||||
{{ else if gt (intVal $ticket.Bonus1) 0 }}
|
||||
{{ $b := intVal $ticket.Bonus1 }}
|
||||
<div class="ball game-{{lower $ticket.GameType}} bonus{{ if inSlice $b $ticket.MatchedDraw.BonusBalls }} matched-bonus{{ end }}">
|
||||
{{ $b }}
|
||||
</div>
|
||||
{{ else }}
|
||||
<span style="color: lightgray;">–</span>
|
||||
{{ end }}
|
||||
</td>
|
||||
<td>{{ .PurchaseDate }}</td>
|
||||
<td>{{ .PurchaseMethod }}</td>
|
||||
<td>
|
||||
{{ if .ImagePath }}
|
||||
<a href="/{{ .ImagePath }}" target="_blank">View</a>
|
||||
{{ else }}–{{ end }}
|
||||
</td>
|
||||
<td>
|
||||
{{ if $ticket.IsWinner }}
|
||||
{{ if eq $ticket.PrizeLabel "" }}
|
||||
<span class="text-yellow-500 italic">pending</span>
|
||||
{{ else if eq $ticket.PrizeLabel "Free Ticket" }}
|
||||
🎟️ {{ $ticket.PrizeLabel }}
|
||||
{{ else }}
|
||||
💷 {{ $ticket.PrizeLabel }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
–
|
||||
{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
Reference in New Issue
Block a user