| | <!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 { |
| | 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 { |
| | 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 { |
| | 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 { |
| | 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 { |
| | 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-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-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; |
| | } |
| | |
| | |
| | @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; |
| | } |
| | } |
| | |
| | |
| | @keyframes fadeIn { |
| | from { opacity: 0; } |
| | to { opacity: 1; } |
| | } |
| | |
| | .fade-in { |
| | animation: fadeIn 0.5s ease-in-out; |
| | } |
| | </style> |
| | </head> |
| | <body> |
| | <div class="container"> |
| | |
| | <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> |
| |
|
| | |
| | <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> |
| |
|
| | |
| | <div class="players-grid" id="players-container"> |
| | |
| | <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> |
| |
|
| | |
| | <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> |
| |
|
| | |
| | <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">×</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> |
| |
|
| | |
| | <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">×</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> |
| | |
| | </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> |
| |
|
| | |
| | <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">×</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> |
| | |
| | </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> |
| |
|
| | |
| | <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">×</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> |
| | |
| | </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> |
| |
|
| | |
| | <div class="toast-container" id="toast-container"></div> |
| |
|
| | <script> |
| | |
| | const state = { |
| | session: { |
| | name: 'Sessão VIP', |
| | startTime: new Date(), |
| | players: [], |
| | transactions: [], |
| | cash: 0, |
| | pix: 0 |
| | } |
| | }; |
| | |
| | |
| | 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') |
| | }; |
| | |
| | |
| | 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() { |
| | |
| | const chipsInPlay = state.session.players.reduce((sum, player) => { |
| | return sum + calculateBalance(player); |
| | }, 0); |
| | |
| | |
| | const totalChipsBought = state.session.players.reduce((sum, player) => { |
| | return sum + player.buyIns.reduce((playerSum, buyIn) => playerSum + buyIn.amount, 0); |
| | }, 0); |
| | |
| | |
| | const pendingDebits = state.session.players.reduce((sum, player) => { |
| | const balance = calculateBalance(player); |
| | return balance < 0 ? sum + Math.abs(balance) : sum; |
| | }, 0); |
| | |
| | |
| | const pendingCredits = state.session.players.reduce((sum, player) => { |
| | const balance = calculateBalance(player); |
| | return balance > 0 ? sum + balance : sum; |
| | }, 0); |
| | |
| | |
| | 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() { |
| | |
| | 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>'; |
| | |
| | |
| | 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); |
| | |
| | |
| | const deleteBtn = playerCard.querySelector('.player-action-btn'); |
| | deleteBtn.addEventListener('click', () => deletePlayer(player.id)); |
| | }); |
| | |
| | updateSessionSummary(); |
| | } |
| | |
| | |
| | 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() |
| | }); |
| | |
| | |
| | if (paymentMethod === 'cash') { |
| | state.session.cash += parseFloat(initialBuyin); |
| | } else { |
| | state.session.pix += parseFloat(initialBuyin); |
| | } |
| | } |
| | |
| | state.session.players.push(newPlayer); |
| | renderPlayers(); |
| | populatePlayerSelects(); |
| | |
| | |
| | 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!`); |
| | } |
| | } |
| | |
| | |
| | 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() |
| | }); |
| | |
| | |
| | if (paymentMethod === 'cash') { |
| | state.session.cash += parseFloat(amount); |
| | } else { |
| | state.session.pix += parseFloat(amount); |
| | } |
| | |
| | |
| | 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() |
| | }); |
| | |
| | |
| | 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() |
| | }); |
| | |
| | |
| | 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); |
| | } |
| | } |
| | |
| | |
| | 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}`); |
| | } |
| | } |
| | |
| | |
| | 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'); |
| | }); |
| | |
| | |
| | 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'); |
| | }); |
| | |
| | |
| | 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); |
| | |
| | |
| | elements.playerNameInput.value = ''; |
| | elements.playerInitialBuyin.value = ''; |
| | |
| | |
| | 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); |
| | |
| | |
| | elements.buyChipsPlayerSelect.value = ''; |
| | elements.buyChipsAmount.value = ''; |
| | |
| | |
| | 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); |
| | |
| | |
| | elements.cashOutPlayerSelect.value = ''; |
| | elements.cashOutAmount.value = ''; |
| | |
| | |
| | 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); |
| | |
| | |
| | elements.paymentPlayerSelect.value = ''; |
| | elements.paymentAmount.value = ''; |
| | |
| | |
| | elements.registerPaymentModal.classList.remove('active'); |
| | }); |
| | |
| | |
| | document.querySelectorAll('.modal-overlay').forEach(overlay => { |
| | overlay.addEventListener('click', (e) => { |
| | if (e.target === overlay) { |
| | overlay.classList.remove('active'); |
| | } |
| | }); |
| | }); |
| | |
| | |
| | document.addEventListener('keydown', (e) => { |
| | if (e.key === 'Escape') { |
| | document.querySelectorAll('.modal-overlay').forEach(overlay => { |
| | overlay.classList.remove('active'); |
| | }); |
| | } |
| | }); |
| | |
| | |
| | function init() { |
| | |
| | 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() } |
| | ] |
| | } |
| | ]; |
| | |
| | |
| | if (state.session.players.length === 0) { |
| | state.session.players = players; |
| | state.session.cash = 1500; |
| | state.session.pix = 1000; |
| | |
| | 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(); |
| | |
| | |
| | updateSessionTime(); |
| | setInterval(updateSessionTime, 1000); |
| | } |
| | |
| | |
| | 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> |