kabal / index.html
castro777's picture
Add 2 files
4c1660b verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CashGame Manager</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--bg-primary: #121212;
--bg-secondary: #1C1C1C;
--bg-tertiary: #262626;
--accent-blue: #2196F3;
--accent-green: #4CAF50;
--accent-yellow: #FFC107;
--accent-red: #F44336;
--text-primary: #FFFFFF;
--text-secondary: #B3B3B3;
--shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Roboto', sans-serif;
}
body {
background-color: var(--bg-primary);
color: var(--text-primary);
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* Header */
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid var(--bg-tertiary);
}
.header-title {
font-size: 28px;
font-weight: 700;
}
.header-session {
display: flex;
align-items: center;
gap: 20px;
}
.session-info {
display: flex;
flex-direction: column;
gap: 5px;
}
.session-name {
font-size: 18px;
font-weight: 500;
}
.session-duration {
font-size: 14px;
color: var(--text-secondary);
}
.status-badge {
padding: 5px 10px;
border-radius: 20px;
font-size: 12px;
font-weight: 500;
background-color: var(--accent-green);
}
/* Quick Actions */
.quick-actions {
display: flex;
gap: 15px;
margin-bottom: 30px;
flex-wrap: wrap;
}
.action-btn {
background-color: var(--bg-tertiary);
color: var(--text-primary);
border: none;
border-radius: 8px;
padding: 12px 20px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s;
box-shadow: var(--shadow);
}
.action-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
}
.action-btn i {
font-size: 16px;
}
/* Players Grid */
.players-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.no-players {
grid-column: 1 / -1;
text-align: center;
color: var(--text-secondary);
padding: 40px;
font-size: 18px;
}
/* Player Card */
.player-card {
background-color: var(--bg-secondary);
border-radius: 12px;
padding: 20px;
box-shadow: var(--shadow);
transition: all 0.3s;
}
.player-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.4);
}
.player-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid var(--bg-tertiary);
}
.player-name {
font-size: 18px;
font-weight: 500;
}
.player-actions {
display: flex;
gap: 10px;
}
.player-action-btn {
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
font-size: 14px;
transition: color 0.2s;
}
.player-action-btn:hover {
color: var(--text-primary);
}
.player-balance {
font-size: 24px;
font-weight: 700;
text-align: center;
margin-bottom: 20px;
}
.player-balance.positive {
color: var(--accent-green);
}
.player-balance.negative {
color: var(--accent-red);
}
.player-balance.neutral {
color: var(--text-primary);
}
.player-details {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
}
.detail-card {
background-color: var(--bg-tertiary);
border-radius: 8px;
padding: 12px;
}
.detail-card-title {
font-size: 12px;
margin-bottom: 8px;
color: var(--text-secondary);
}
.detail-card-value {
font-size: 16px;
font-weight: 500;
}
.detail-card.buyins {
border-left: 4px solid var(--accent-blue);
}
.detail-card.cashout {
border-left: 4px solid var(--accent-green);
}
.detail-card.payments {
border-left: 4px solid var(--accent-yellow);
}
/* Summary Section */
.summary-section {
background-color: var(--bg-secondary);
border-radius: 12px;
padding: 20px;
margin-top: 30px;
box-shadow: var(--shadow);
}
.section-title {
font-size: 20px;
font-weight: 500;
margin-bottom: 20px;
}
.summary-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 20px;
}
.summary-card {
background-color: var(--bg-tertiary);
border-radius: 8px;
padding: 15px;
}
.summary-card-title {
font-size: 14px;
color: var(--text-secondary);
margin-bottom: 10px;
}
.summary-card-value {
font-size: 24px;
font-weight: 700;
}
.summary-card.chips-in-play {
border-left: 4px solid var(--accent-blue);
}
.summary-card.chips-bought {
border-left: 4px solid var(--accent-green);
}
.summary-card.pending-debits {
border-left: 4px solid var(--accent-red);
}
.summary-card.pending-credits {
border-left: 4px solid var(--accent-yellow);
}
/* Modal */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
}
.modal-overlay.active {
opacity: 1;
pointer-events: all;
}
.modal {
background-color: var(--bg-secondary);
border-radius: 12px;
width: 100%;
max-width: 500px;
max-height: 90vh;
overflow-y: auto;
transform: translateY(20px);
transition: transform 0.3s;
}
.modal-overlay.active .modal {
transform: translateY(0);
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
border-bottom: 1px solid var(--bg-tertiary);
}
.modal-title {
font-size: 20px;
font-weight: 500;
}
.modal-close {
background: none;
border: none;
color: var(--text-secondary);
font-size: 20px;
cursor: pointer;
transition: color 0.2s;
}
.modal-close:hover {
color: var(--text-primary);
}
.modal-body {
padding: 20px;
}
.form-group {
margin-bottom: 20px;
}
.form-label {
display: block;
margin-bottom: 8px;
font-size: 14px;
color: var(--text-secondary);
}
.form-input {
width: 100%;
padding: 12px;
background-color: var(--bg-tertiary);
border: none;
border-radius: 8px;
color: var(--text-primary);
font-size: 16px;
}
.form-input:focus {
outline: none;
box-shadow: 0 0 0 2px var(--accent-blue);
}
.select-wrapper {
position: relative;
}
.select-wrapper::after {
content: '\f078';
font-family: 'Font Awesome 6 Free';
font-weight: 900;
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
color: var(--text-secondary);
pointer-events: none;
}
.form-select {
width: 100%;
padding: 12px;
background-color: var(--bg-tertiary);
border: none;
border-radius: 8px;
color: var(--text-primary);
font-size: 16px;
appearance: none;
}
.form-select:focus {
outline: none;
box-shadow: 0 0 0 2px var(--accent-blue);
}
.radio-group {
display: flex;
gap: 30px;
margin-bottom: 20px;
}
.radio-option {
display: flex;
align-items: center;
gap: 8px;
}
.radio-input {
appearance: none;
width: 18px;
height: 18px;
border: 2px solid var(--bg-tertiary);
border-radius: 50%;
position: relative;
cursor: pointer;
}
.radio-input:checked {
border-color: var(--accent-blue);
}
.radio-input:checked::after {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 10px;
height: 10px;
background-color: var(--accent-blue);
border-radius: 50%;
}
.radio-label {
font-size: 14px;
cursor: pointer;
}
.modal-footer {
display: flex;
justify-content: flex-end;
gap: 15px;
padding: 20px;
border-top: 1px solid var(--bg-tertiary);
}
.btn {
padding: 10px 20px;
border-radius: 8px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s;
border: none;
}
.btn-primary {
background-color: var(--accent-blue);
color: white;
}
.btn-primary:hover {
background-color: #1976D2;
}
.btn-secondary {
background-color: var(--bg-tertiary);
color: var(--text-primary);
}
.btn-secondary:hover {
background-color: #333333;
}
/* Toast */
.toast-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 1100;
display: flex;
flex-direction: column;
gap: 10px;
}
.toast {
padding: 12px 20px;
border-radius: 8px;
font-size: 14px;
font-weight: 500;
display: flex;
align-items: center;
gap: 10px;
box-shadow: var(--shadow);
transform: translateX(200%);
transition: transform 0.3s;
}
.toast.show {
transform: translateX(0);
}
.toast-success {
background-color: var(--accent-green);
color: white;
}
.toast-error {
background-color: var(--accent-red);
color: white;
}
.toast i {
font-size: 16px;
}
.money-input {
position: relative;
}
.money-input::before {
content: 'R$';
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
color: var(--text-secondary);
}
.money-input input {
padding-left: 35px !important;
}
/* Responsive */
@media (max-width: 768px) {
.players-grid {
grid-template-columns: 1fr;
}
.summary-grid {
grid-template-columns: 1fr;
}
.header {
flex-direction: column;
gap: 20px;
align-items: flex-start;
}
.quick-actions {
justify-content: center;
}
}
/* Animations */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in {
animation: fadeIn 0.5s ease-in-out;
}
</style>
</head>
<body>
<div class="container">
<!-- Header -->
<div class="header fade-in">
<div class="header-title">CashGame Manager</div>
<div class="header-session">
<div class="session-info">
<div class="session-name">Sessão VIP</div>
<div class="session-duration"><i class="fas fa-clock"></i> 02:35:21</div>
</div>
<span class="status-badge">Ativo</span>
</div>
</div>
<!-- Quick Actions -->
<div class="quick-actions fade-in">
<button class="action-btn" id="buy-chips-btn">
<i class="fas fa-plus-circle"></i> Registrar Compra
</button>
<button class="action-btn" id="cash-out-btn">
<i class="fas fa-minus-circle"></i> Registrar Devolução
</button>
<button class="action-btn" id="register-payment-btn">
<i class="fas fa-exchange-alt"></i> Registrar Pagamento
</button>
<button class="action-btn" id="add-player-btn">
<i class="fas fa-user-plus"></i> Adicionar Jogador
</button>
</div>
<!-- Players Grid -->
<div class="players-grid" id="players-container">
<!-- Player cards will be inserted here by JavaScript -->
<div class="no-players">
<i class="fas fa-users-slash" style="font-size: 24px; margin-bottom: 10px;"></i>
<p>Nenhum jogador adicionado</p>
</div>
</div>
<!-- Summary Section -->
<div class="summary-section fade-in">
<h3 class="section-title">Resumo da Sessão</h3>
<div class="summary-grid">
<div class="summary-card chips-in-play">
<div class="summary-card-title">Fichas em Jogo</div>
<div class="summary-card-value">R$ 2,450.00</div>
</div>
<div class="summary-card chips-bought">
<div class="summary-card-title">Fichas Compradas</div>
<div class="summary-card-value">R$ 3,000.00</div>
</div>
<div class="summary-card pending-debits">
<div class="summary-card-title">Débitos Pendentes</div>
<div class="summary-card-value">R$ 550.00</div>
</div>
<div class="summary-card pending-credits">
<div class="summary-card-title">Créditos Pendentes</div>
<div class="summary-card-value">R$ 850.00</div>
</div>
</div>
</div>
</div>
<!-- Add Player Modal -->
<div class="modal-overlay" id="add-player-modal">
<div class="modal">
<div class="modal-header">
<h3 class="modal-title">Adicionar Jogador</h3>
<button class="modal-close" id="close-add-player-modal">&times;</button>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label" for="player-name">Nome do Jogador</label>
<input type="text" class="form-input" id="player-name" placeholder="Digite o nome do jogador">
</div>
<div class="form-group">
<label class="form-label" for="player-initial-buyin">Compra Inicial (opcional)</label>
<div class="money-input">
<input type="number" class="form-input" id="player-initial-buyin" placeholder="0.00" step="0.01">
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" id="cancel-add-player">Cancelar</button>
<button class="btn btn-primary" id="confirm-add-player">Adicionar</button>
</div>
</div>
</div>
<!-- Buy Chips Modal -->
<div class="modal-overlay" id="buy-chips-modal">
<div class="modal">
<div class="modal-header">
<h3 class="modal-title">Registrar Compra de Fichas</h3>
<button class="modal-close" id="close-buy-chips-modal">&times;</button>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label" for="buy-chips-player">Jogador</label>
<div class="select-wrapper">
<select class="form-select" id="buy-chips-player">
<option value="">Selecione um jogador</option>
<!-- Options will be added by JavaScript -->
</select>
</div>
</div>
<div class="form-group">
<label class="form-label" for="buy-chips-amount">Valor</label>
<div class="money-input">
<input type="number" class="form-input" id="buy-chips-amount" placeholder="0.00" step="0.01">
</div>
</div>
<div class="form-group">
<label class="form-label">Método de Pagamento</label>
<div class="radio-group">
<div class="radio-option">
<input type="radio" class="radio-input" name="payment-method" id="cash-method" value="cash" checked>
<label class="radio-label" for="cash-method">Dinheiro</label>
</div>
<div class="radio-option">
<input type="radio" class="radio-input" name="payment-method" id="pix-method" value="pix">
<label class="radio-label" for="pix-method">PIX</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" id="cancel-buy-chips">Cancelar</button>
<button class="btn btn-primary" id="confirm-buy-chips">Registrar</button>
</div>
</div>
</div>
<!-- Cash Out Modal -->
<div class="modal-overlay" id="cash-out-modal">
<div class="modal">
<div class="modal-header">
<h3 class="modal-title">Registrar Devolução de Fichas</h3>
<button class="modal-close" id="close-cash-out-modal">&times;</button>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label" for="cash-out-player">Jogador</label>
<div class="select-wrapper">
<select class="form-select" id="cash-out-player">
<option value="">Selecione um jogador</option>
<!-- Options will be added by JavaScript -->
</select>
</div>
</div>
<div class="form-group">
<label class="form-label" for="cash-out-amount">Valor</label>
<div class="money-input">
<input type="number" class="form-input" id="cash-out-amount" placeholder="0.00" step="0.01">
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" id="cancel-cash-out">Cancelar</button>
<button class="btn btn-primary" id="confirm-cash-out">Registrar</button>
</div>
</div>
</div>
<!-- Register Payment Modal -->
<div class="modal-overlay" id="register-payment-modal">
<div class="modal">
<div class="modal-header">
<h3 class="modal-title">Registrar Pagamento</h3>
<button class="modal-close" id="close-register-payment-modal">&times;</button>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label" for="payment-type">Tipo de Pagamento</label>
<div class="radio-group">
<div class="radio-option">
<input type="radio" class="radio-input" name="payment-type" id="payment-to" value="to" checked>
<label class="radio-label" for="payment-to">Jogador → Casa</label>
</div>
<div class="radio-option">
<input type="radio" class="radio-input" name="payment-type" id="payment-from" value="from">
<label class="radio-label" for="payment-from">Casa → Jogador</label>
</div>
</div>
</div>
<div class="form-group">
<label class="form-label" for="payment-player">Jogador</label>
<div class="select-wrapper">
<select class="form-select" id="payment-player">
<option value="">Selecione um jogador</option>
<!-- Options will be added by JavaScript -->
</select>
</div>
</div>
<div class="form-group">
<label class="form-label" for="payment-amount">Valor</label>
<div class="money-input">
<input type="number" class="form-input" id="payment-amount" placeholder="0.00" step="0.01">
</div>
</div>
<div class="form-group">
<label class="form-label">Método de Pagamento</label>
<div class="radio-group">
<div class="radio-option">
<input type="radio" class="radio-input" name="payment-method-payment" id="cash-method-payment" value="cash" checked>
<label class="radio-label" for="cash-method-payment">Dinheiro</label>
</div>
<div class="radio-option">
<input type="radio" class="radio-input" name="payment-method-payment" id="pix-method-payment" value="pix">
<label class="radio-label" for="pix-method-payment">PIX</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" id="cancel-payment">Cancelar</button>
<button class="btn btn-primary" id="confirm-payment">Registrar</button>
</div>
</div>
</div>
<!-- Toast Container -->
<div class="toast-container" id="toast-container"></div>
<script>
// State management
const state = {
session: {
name: 'Sessão VIP',
startTime: new Date(),
players: [],
transactions: [],
cash: 0,
pix: 0
}
};
// DOM Elements
const elements = {
playersContainer: document.getElementById('players-container'),
addPlayerBtn: document.getElementById('add-player-btn'),
buyChipsBtn: document.getElementById('buy-chips-btn'),
cashOutBtn: document.getElementById('cash-out-btn'),
registerPaymentBtn: document.getElementById('register-payment-btn'),
addPlayerModal: document.getElementById('add-player-modal'),
buyChipsModal: document.getElementById('buy-chips-modal'),
cashOutModal: document.getElementById('cash-out-modal'),
registerPaymentModal: document.getElementById('register-payment-modal'),
closeAddPlayerModal: document.getElementById('close-add-player-modal'),
closeBuyChipsModal: document.getElementById('close-buy-chips-modal'),
closeCashOutModal: document.getElementById('close-cash-out-modal'),
closeRegisterPaymentModal: document.getElementById('close-register-payment-modal'),
cancelAddPlayer: document.getElementById('cancel-add-player'),
cancelBuyChips: document.getElementById('cancel-buy-chips'),
cancelCashOut: document.getElementById('cancel-cash-out'),
cancelPayment: document.getElementById('cancel-payment'),
confirmAddPlayer: document.getElementById('confirm-add-player'),
confirmBuyChips: document.getElementById('confirm-buy-chips'),
confirmCashOut: document.getElementById('confirm-cash-out'),
confirmPayment: document.getElementById('confirm-payment'),
playerNameInput: document.getElementById('player-name'),
playerInitialBuyin: document.getElementById('player-initial-buyin'),
buyChipsPlayerSelect: document.getElementById('buy-chips-player'),
buyChipsAmount: document.getElementById('buy-chips-amount'),
cashOutPlayerSelect: document.getElementById('cash-out-player'),
cashOutAmount: document.getElementById('cash-out-amount'),
paymentPlayerSelect: document.getElementById('payment-player'),
paymentAmount: document.getElementById('payment-amount'),
toastContainer: document.getElementById('toast-container')
};
// Utility functions
function formatCurrency(value) {
return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(value);
}
function formatTime(durationInSeconds) {
const hours = Math.floor(durationInSeconds / 3600);
const minutes = Math.floor((durationInSeconds % 3600) / 60);
const seconds = durationInSeconds % 60;
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
}
function showToast(message, type = 'success') {
const toast = document.createElement('div');
toast.className = `toast toast-${type}`;
const icon = document.createElement('i');
icon.className = type === 'success' ? 'fas fa-check-circle' : 'fas fa-exclamation-circle';
toast.appendChild(icon);
const text = document.createTextNode(message);
toast.appendChild(text);
elements.toastContainer.appendChild(toast);
setTimeout(() => {
toast.classList.add('show');
}, 10);
setTimeout(() => {
toast.remove();
}, 5000);
}
function calculateBalance(player) {
const totalBuyIns = player.buyIns.reduce((sum, buyIn) => sum + buyIn.amount, 0);
const totalCashOuts = player.cashOuts.reduce((sum, cashOut) => sum + cashOut.amount, 0);
const totalPayments = player.payments.reduce((sum, payment) => {
return payment.type === 'to' ? sum + payment.amount : sum - payment.amount;
}, 0);
return totalBuyIns - totalCashOuts + totalPayments;
}
function updateSessionSummary() {
// Calculate chips in play
const chipsInPlay = state.session.players.reduce((sum, player) => {
return sum + calculateBalance(player);
}, 0);
// Calculate total chips bought
const totalChipsBought = state.session.players.reduce((sum, player) => {
return sum + player.buyIns.reduce((playerSum, buyIn) => playerSum + buyIn.amount, 0);
}, 0);
// Calculate pending debits (players with negative balance)
const pendingDebits = state.session.players.reduce((sum, player) => {
const balance = calculateBalance(player);
return balance < 0 ? sum + Math.abs(balance) : sum;
}, 0);
// Calculate pending credits (players with positive balance)
const pendingCredits = state.session.players.reduce((sum, player) => {
const balance = calculateBalance(player);
return balance > 0 ? sum + balance : sum;
}, 0);
// Update the UI
document.querySelector('.summary-card.chips-in-play .summary-card-value').textContent = formatCurrency(chipsInPlay);
document.querySelector('.summary-card.chips-bought .summary-card-value').textContent = formatCurrency(totalChipsBought);
document.querySelector('.summary-card.pending-debits .summary-card-value').textContent = formatCurrency(pendingDebits);
document.querySelector('.summary-card.pending-credits .summary-card-value').textContent = formatCurrency(pendingCredits);
}
function updateSessionTime() {
const now = new Date();
const diffInSeconds = Math.floor((now - state.session.startTime) / 1000);
document.querySelector('.session-duration').innerHTML = `<i class="fas fa-clock"></i> ${formatTime(diffInSeconds)}`;
}
function populatePlayerSelects() {
// Clear existing options
elements.buyChipsPlayerSelect.innerHTML = '<option value="">Selecione um jogador</option>';
elements.cashOutPlayerSelect.innerHTML = '<option value="">Selecione um jogador</option>';
elements.paymentPlayerSelect.innerHTML = '<option value="">Selecione um jogador</option>';
// Add current players to the selects
state.session.players.forEach(player => {
const option = document.createElement('option');
option.value = player.id;
option.textContent = player.name;
elements.buyChipsPlayerSelect.appendChild(option.cloneNode(true));
elements.cashOutPlayerSelect.appendChild(option.cloneNode(true));
elements.paymentPlayerSelect.appendChild(option.cloneNode(true));
});
}
function renderPlayers() {
elements.playersContainer.innerHTML = '';
if (state.session.players.length === 0) {
const noPlayers = document.createElement('div');
noPlayers.className = 'no-players';
noPlayers.innerHTML = `
<i class="fas fa-users-slash" style="font-size: 24px; margin-bottom: 10px;"></i>
<p>Nenhum jogador adicionado</p>
`;
elements.playersContainer.appendChild(noPlayers);
return;
}
state.session.players.forEach(player => {
const totalBuyIns = player.buyIns.reduce((sum, buyIn) => sum + buyIn.amount, 0);
const totalCashOuts = player.cashOuts.reduce((sum, cashOut) => sum + cashOut.amount, 0);
const totalPayments = player.payments.reduce((sum, payment) => {
return payment.type === 'to' ? sum + payment.amount : sum - payment.amount;
}, 0);
const balance = calculateBalance(player);
const balanceClass = balance > 0 ? 'positive' : balance < 0 ? 'negative' : 'neutral';
const balanceSymbol = balance > 0 ? '+' : '';
const playerCard = document.createElement('div');
playerCard.className = 'player-card fade-in';
playerCard.innerHTML = `
<div class="player-header">
<div class="player-name">${player.name}</div>
<div class="player-actions">
<button class="player-action-btn" data-id="${player.id}">
<i class="fas fa-trash-alt"></i>
</button>
</div>
</div>
<div class="player-balance ${balanceClass}">
${balanceSymbol}${formatCurrency(balance)}
</div>
<div class="player-details">
<div class="detail-card buyins">
<div class="detail-card-title">COMPRAS</div>
<div class="detail-card-value">${formatCurrency(totalBuyIns)}</div>
</div>
<div class="detail-card cashout">
<div class="detail-card-title">DEVOLUÇÕES</div>
<div class="detail-card-value">${formatCurrency(totalCashOuts)}</div>
</div>
<div class="detail-card payments">
<div class="detail-card-title">PAGAMENTOS</div>
<div class="detail-card-value">${formatCurrency(totalPayments)}</div>
</div>
</div>
`;
elements.playersContainer.appendChild(playerCard);
// Add event listener to delete button
const deleteBtn = playerCard.querySelector('.player-action-btn');
deleteBtn.addEventListener('click', () => deletePlayer(player.id));
});
updateSessionSummary();
}
// Player management
function addPlayer(name, initialBuyin = 0) {
const newPlayer = {
id: Date.now().toString(),
name: name,
buyIns: [],
cashOuts: [],
payments: []
};
if (initialBuyin > 0) {
const paymentMethod = document.querySelector('input[name="payment-method"]:checked').value;
newPlayer.buyIns.push({
id: Date.now().toString(),
amount: parseFloat(initialBuyin),
paymentMethod: paymentMethod,
timestamp: new Date()
});
// Update session totals
if (paymentMethod === 'cash') {
state.session.cash += parseFloat(initialBuyin);
} else {
state.session.pix += parseFloat(initialBuyin);
}
}
state.session.players.push(newPlayer);
renderPlayers();
populatePlayerSelects();
// Add transaction record
if (initialBuyin > 0) {
state.session.transactions.push({
type: 'buy-in',
playerId: newPlayer.id,
playerName: newPlayer.name,
amount: parseFloat(initialBuyin),
paymentMethod: paymentMethod,
timestamp: new Date()
});
}
showToast(`Jogador ${name} adicionado com sucesso!`);
}
function deletePlayer(playerId) {
const playerIndex = state.session.players.findIndex(p => p.id === playerId);
if (playerIndex !== -1) {
const playerName = state.session.players[playerIndex].name;
state.session.players.splice(playerIndex, 1);
renderPlayers();
populatePlayerSelects();
showToast(`Jogador ${playerName} removido com sucesso!`);
}
}
// Transaction management
function registerBuyIn(playerId, amount, paymentMethod) {
const player = state.session.players.find(p => p.id === playerId);
if (player) {
player.buyIns.push({
id: Date.now().toString(),
amount: parseFloat(amount),
paymentMethod: paymentMethod,
timestamp: new Date()
});
// Update session totals
if (paymentMethod === 'cash') {
state.session.cash += parseFloat(amount);
} else {
state.session.pix += parseFloat(amount);
}
// Add transaction record
state.session.transactions.push({
type: 'buy-in',
playerId: playerId,
playerName: player.name,
amount: parseFloat(amount),
paymentMethod: paymentMethod,
timestamp: new Date()
});
renderPlayers();
showToast(`Compra de ${formatCurrency(amount)} registrada para ${player.name}`);
}
}
function registerCashOut(playerId, amount) {
const player = state.session.players.find(p => p.id === playerId);
if (player) {
player.cashOuts.push({
id: Date.now().toString(),
amount: parseFloat(amount),
timestamp: new Date()
});
// Add transaction record
state.session.transactions.push({
type: 'cash-out',
playerId: playerId,
playerName: player.name,
amount: parseFloat(amount),
timestamp: new Date()
});
renderPlayers();
showToast(`Devolução de ${formatCurrency(amount)} registrada para ${player.name}`);
}
}
function registerPayment(playerId, amount, type, paymentMethod) {
const player = state.session.players.find(p => p.id === playerId);
if (player) {
player.payments.push({
id: Date.now().toString(),
amount: parseFloat(amount),
type: type,
paymentMethod: paymentMethod,
timestamp: new Date()
});
// Update session totals
if (type === 'to') {
if (paymentMethod === 'cash') {
state.session.cash += parseFloat(amount);
} else {
state.session.pix += parseFloat(amount);
}
} else {
if (paymentMethod === 'cash') {
state.session.cash -= parseFloat(amount);
} else {
state.session.pix -= parseFloat(amount);
}
}
// Add transaction record
state.session.transactions.push({
type: type === 'to' ? 'payment-to-house' : 'payment-from-house',
playerId: playerId,
playerName: player.name,
amount: parseFloat(amount),
paymentMethod: paymentMethod,
timestamp: new Date()
});
renderPlayers();
showToast(`Pagamento de ${formatCurrency(amount)} ${type === 'to' ? 'para' : 'de'} a casa registrado para ${player.name}`);
}
}
// Event listeners
elements.addPlayerBtn.addEventListener('click', () => {
elements.addPlayerModal.classList.add('active');
});
elements.buyChipsBtn.addEventListener('click', () => {
elements.buyChipsModal.classList.add('active');
});
elements.cashOutBtn.addEventListener('click', () => {
elements.cashOutModal.classList.add('active');
});
elements.registerPaymentBtn.addEventListener('click', () => {
elements.registerPaymentModal.classList.add('active');
});
// Close modals
elements.closeAddPlayerModal.addEventListener('click', () => {
elements.addPlayerModal.classList.remove('active');
});
elements.closeBuyChipsModal.addEventListener('click', () => {
elements.buyChipsModal.classList.remove('active');
});
elements.closeCashOutModal.addEventListener('click', () => {
elements.cashOutModal.classList.remove('active');
});
elements.closeRegisterPaymentModal.addEventListener('click', () => {
elements.registerPaymentModal.classList.remove('active');
});
elements.cancelAddPlayer.addEventListener('click', () => {
elements.addPlayerModal.classList.remove('active');
});
elements.cancelBuyChips.addEventListener('click', () => {
elements.buyChipsModal.classList.remove('active');
});
elements.cancelCashOut.addEventListener('click', () => {
elements.cashOutModal.classList.remove('active');
});
elements.cancelPayment.addEventListener('click', () => {
elements.registerPaymentModal.classList.remove('active');
});
// Confirm actions
elements.confirmAddPlayer.addEventListener('click', () => {
const name = elements.playerNameInput.value.trim();
const initialBuyin = elements.playerInitialBuyin.value || 0;
if (!name) {
showToast('Por favor, digite o nome do jogador', 'error');
return;
}
addPlayer(name, initialBuyin);
// Reset form
elements.playerNameInput.value = '';
elements.playerInitialBuyin.value = '';
// Close modal
elements.addPlayerModal.classList.remove('active');
});
elements.confirmBuyChips.addEventListener('click', () => {
const playerId = elements.buyChipsPlayerSelect.value;
const amount = elements.buyChipsAmount.value;
const paymentMethod = document.querySelector('input[name="payment-method"]:checked').value;
if (!playerId) {
showToast('Por favor, selecione um jogador', 'error');
return;
}
if (!amount || parseFloat(amount) <= 0) {
showToast('Por favor, digite um valor válido', 'error');
return;
}
registerBuyIn(playerId, amount, paymentMethod);
// Reset form
elements.buyChipsPlayerSelect.value = '';
elements.buyChipsAmount.value = '';
// Close modal
elements.buyChipsModal.classList.remove('active');
});
elements.confirmCashOut.addEventListener('click', () => {
const playerId = elements.cashOutPlayerSelect.value;
const amount = elements.cashOutAmount.value;
if (!playerId) {
showToast('Por favor, selecione um jogador', 'error');
return;
}
if (!amount || parseFloat(amount) <= 0) {
showToast('Por favor, digite um valor válido', 'error');
return;
}
registerCashOut(playerId, amount);
// Reset form
elements.cashOutPlayerSelect.value = '';
elements.cashOutAmount.value = '';
// Close modal
elements.cashOutModal.classList.remove('active');
});
elements.confirmPayment.addEventListener('click', () => {
const type = document.querySelector('input[name="payment-type"]:checked').value;
const playerId = elements.paymentPlayerSelect.value;
const amount = elements.paymentAmount.value;
const paymentMethod = document.querySelector('input[name="payment-method-payment"]:checked').value;
if (!playerId) {
showToast('Por favor, selecione um jogador', 'error');
return;
}
if (!amount || parseFloat(amount) <= 0) {
showToast('Por favor, digite um valor válido', 'error');
return;
}
registerPayment(playerId, amount, type, paymentMethod);
// Reset form
elements.paymentPlayerSelect.value = '';
elements.paymentAmount.value = '';
// Close modal
elements.registerPaymentModal.classList.remove('active');
});
// Close modals when clicking outside
document.querySelectorAll('.modal-overlay').forEach(overlay => {
overlay.addEventListener('click', (e) => {
if (e.target === overlay) {
overlay.classList.remove('active');
}
});
});
// Close all modals on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
document.querySelectorAll('.modal-overlay').forEach(overlay => {
overlay.classList.remove('active');
});
}
});
// Initialize
function init() {
// Set up some initial test data
const players = [
{
id: '1',
name: 'João Silva',
buyIns: [
{ id: '1-1', amount: 500, paymentMethod: 'cash', timestamp: new Date() }
],
cashOuts: [],
payments: []
},
{
id: '2',
name: 'Maria Santos',
buyIns: [
{ id: '2-1', amount: 1000, paymentMethod: 'pix', timestamp: new Date() },
{ id: '2-2', amount: 500, paymentMethod: 'cash', timestamp: new Date() }
],
cashOuts: [
{ id: '2-3', amount: 300, timestamp: new Date() }
],
payments: [
{ id: '2-4', amount: 200, type: 'to', paymentMethod: 'cash', timestamp: new Date() }
]
},
{
id: '3',
name: 'Carlos Oliveira',
buyIns: [
{ id: '3-1', amount: 1000, paymentMethod: 'cash', timestamp: new Date() }
],
cashOuts: [],
payments: [
{ id: '3-2', amount: 350, type: 'from', paymentMethod: 'pix', timestamp: new Date() }
]
}
];
// Initialize session with test data (only if empty)
if (state.session.players.length === 0) {
state.session.players = players;
state.session.cash = 1500; // From João (500) + Maria (500) + Carlos (1000) = 2000 total cash, but Maria paid 200 and Carlos received 350
state.session.pix = 1000; // From Maria's first buy-in
players.forEach(player => {
if (player.name === 'João Silva') {
state.session.transactions.push({
type: 'buy-in',
playerId: player.id,
playerName: player.name,
amount: 500,
paymentMethod: 'cash',
timestamp: new Date()
});
} else if (player.name === 'Maria Santos') {
state.session.transactions.push({
type: 'buy-in',
playerId: player.id,
playerName: player.name,
amount: 1000,
paymentMethod: 'pix',
timestamp: new Date()
});
state.session.transactions.push({
type: 'buy-in',
playerId: player.id,
playerName: player.name,
amount: 500,
paymentMethod: 'cash',
timestamp: new Date()
});
state.session.transactions.push({
type: 'cash-out',
playerId: player.id,
playerName: player.name,
amount: 300,
timestamp: new Date()
});
state.session.transactions.push({
type: 'payment-to-house',
playerId: player.id,
playerName: player.name,
amount: 200,
paymentMethod: 'cash',
timestamp: new Date()
});
} else if (player.name === 'Carlos Oliveira') {
state.session.transactions.push({
type: 'buy-in',
playerId: player.id,
playerName: player.name,
amount: 1000,
paymentMethod: 'cash',
timestamp: new Date()
});
state.session.transactions.push({
type: 'payment-from-house',
playerId: player.id,
playerName: player.name,
amount: 350,
paymentMethod: 'pix',
timestamp: new Date()
});
}
});
}
renderPlayers();
populatePlayerSelects();
// Update session time every second
updateSessionTime();
setInterval(updateSessionTime, 1000);
}
// Start the application
init();
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
</html>