v0.3.0-prod

This commit is contained in:
Mateusz Gruszczyński committed 2026-11-04 14:57:48 +01:00
1 parent 387933957e
commit 9d093b691c
21 files changed
+1239 -180

No files matched your search

+113 -86
View File
@@ -4,99 +4,126 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Utwórz kanał</title>
<link rel="stylesheet" href="/assets/app.css">
<link rel="stylesheet" href="{{asset "app.css"}}">
<script src="{{asset "app.js"}}" defer></script>
</head>
<body class="channel-page">
<main class="channel-shell">
<section class="channel-card">
<div class="channel-topbar">
<a class="back-link" href="/stats">Statystyki
</a>
<a class="back-link" href="{{.VoiceURL}}" target="_top">Połącz z TS3</a>
</div>
<div class="channel-title">
<div>
<p class="eyebrow">TeamSpeak 3</p>
<h1>Utwórz swój kanał</h1>
<p>Aplikacja wykryje Twojego klienta, utworzy kanał, nada prawa i przeniesie Cię automatycznie.</p>
</div>
</div>
{{if .Error}}<div class="alert alert-danger">{{.Error}}</div>{{end}}
{{if .Success}}
<div class="alert alert-success">
<strong>Kanał został utworzony.</strong>
<span>{{.Success}} ID kanału: {{.ChannelID}}</span>
</div>
<div class="button-row">
<a class="btn btn-primary grow" href="{{.VoiceURL}}" target="_top">Otwórz TeamSpeak</a>
<a class="btn btn-ghost" href="/stats">Statystyki</a>
</div>
{{else}}
{{if eq (len .Clients) 0}}{{if not .Client}}
<div class="empty-state">
<h2>Nie wykryto klienta TS3</h2>
<p>Połącz się z serwerem TeamSpeak, a następnie odśwież stronę.</p>
<div class="button-row">
<a class="btn btn-primary grow" href="{{.VoiceURL}}" target="_top">Połącz z TeamSpeak</a>
<a class="btn btn-ghost" href="">Odśwież</a>
<body>
{{template "icons" .}}
<main class="channel-view">
<div class="channel-shell">
<section class="channel-card">
<div class="channel-topbar">
<a href="/stats"><svg class="icon"><use href="#icon-arrow-left"/></svg>Statystyki</a>
<div class="channel-topbar-right">
<a href="{{.VoiceURL}}" target="_top"><svg class="icon"><use href="#icon-zap"/></svg>Połącz z TS3</a>
<button class="theme-toggle" type="button" aria-label="Przełącz jasny/ciemny motyw" title="Jasny / ciemny motyw">
<svg class="icon ic-sun"><use href="#icon-sun"/></svg>
<svg class="icon ic-moon"><use href="#icon-moon"/></svg>
</button>
</div>
</div>
{{end}}{{end}}
{{if gt (len .Clients) 1}}
<div class="selection-box">
<h2>Wybierz swojego klienta</h2>
<p>Pod tym samym adresem IP jest kilka osób. Kod potwierdzający przyjdzie jako prywatna wiadomość na TS3.</p>
<div class="client-list">
{{range .Clients}}
<form method="post" action="/channel/verify/start">
<input type="hidden" name="form_token" value="{{$.FormToken}}">
<input type="hidden" name="clid" value="{{.ID}}">
<button type="submit" class="client-choice">
<span class="avatar" aria-hidden="true">{{printf "%.1s" .Nick}}</span>
<span><strong>{{.Nick}}</strong><small>Wyślij kod weryfikacyjny</small></span></button>
<div class="channel-title">
<svg class="icon"><use href="#icon-headset"/></svg>
<div>
<p class="eyebrow">TeamSpeak 3</p>
<h1>Utwórz swój kanał</h1>
<p>Aplikacja wykryje Twojego klienta, utworzy kanał, nada prawa i przeniesie Cię automatycznie.</p>
</div>
</div>
<div class="channel-body">
{{if .Error}}<div class="alert danger"><svg class="icon"><use href="#icon-circle-alert"/></svg><span>{{.Error}}</span></div>{{end}}
{{if .Success}}
<div class="alert success">
<svg class="icon"><use href="#icon-check-circle"/></svg>
<span><strong>Kanał został utworzony.</strong><br>{{.Success}} ID kanału: {{.ChannelID}}</span>
</div>
<div class="button-row">
<a class="btn primary lg" href="{{.VoiceURL}}" target="_top"><svg class="icon"><use href="#icon-zap"/></svg>Otwórz TeamSpeak</a>
<a class="btn ghost" href="/stats">Statystyki</a>
</div>
{{else}}
{{if eq (len .Clients) 0}}{{if not .Client}}
<div class="empty-state">
<h2>Nie wykryto klienta TS3</h2>
<p>Połącz się z serwerem TeamSpeak, a następnie odśwież stronę.</p>
<div class="button-row">
<a class="btn primary lg" href="{{.VoiceURL}}" target="_top"><svg class="icon"><use href="#icon-zap"/></svg>Połącz z TeamSpeak</a>
<a class="btn ghost" href=""><svg class="icon"><use href="#icon-refresh-cw"/></svg>Odśwież</a>
</div>
</div>
{{end}}{{end}}
{{if gt (len .Clients) 1}}
<div class="selection-box">
<h2>Wybierz swojego klienta</h2>
<p>Pod tym samym adresem IP jest kilka osób. Kod potwierdzający przyjdzie jako prywatna wiadomość na TS3.</p>
<div class="client-list">
{{range .Clients}}
<form method="post" action="/channel/verify/start">
<input type="hidden" name="form_token" value="{{$.FormToken}}">
<input type="hidden" name="clid" value="{{.ID}}">
<button type="submit" class="client-choice">
<span class="avatar" aria-hidden="true">{{printf "%.1s" .Nick}}</span>
<span class="meta"><strong>{{.Nick}}</strong><small>Wyślij kod weryfikacyjny</small></span>
</button>
</form>
{{end}}
</div>
</div>
{{end}}
{{if .Client}}
<div class="client-badge">
<span class="dot" aria-hidden="true"></span>
<span>Wykryty klient</span>
<strong>{{.Client.Nick}}</strong>
</div>
<form method="post" action="/channel/create">
<input type="hidden" name="form_token" value="{{.FormToken}}">
<input type="hidden" name="client_token" value="{{.ClientToken}}">
<div class="field">
<label for="channel-name"><svg class="icon"><use href="#icon-hash"/></svg>Nazwa kanału</label>
<input id="channel-name" name="name" maxlength="40" autocomplete="off" placeholder="Np. Pokój Mateusza" value="{{.Name}}">
<small>Pozostaw puste, aby wygenerować nazwę automatycznie.</small>
</div>
<div class="form-grid">
<div class="field">
<label for="channel-password"><svg class="icon"><use href="#icon-lock"/></svg>Hasło</label>
<input id="channel-password" name="password" maxlength="64" type="password" autocomplete="new-password" placeholder="Opcjonalne">
</div>
<div class="field">
<label for="channel-maxclients"><svg class="icon"><use href="#icon-users"/></svg>Limit użytkowników</label>
<input id="channel-maxclients" name="maxclients" type="number" min="0" max="512" placeholder="0 = bez limitu" value="{{.MaxClients}}">
</div>
</div>
<div class="field wide">
<label for="channel-topic"><svg class="icon"><use href="#icon-sliders"/></svg>Temat / opis</label>
<input id="channel-topic" name="topic" maxlength="255" autocomplete="off" placeholder="Opcjonalne" value="{{.Topic}}">
</div>
<div class="field wide">
<label for="channel-codec-quality"><svg class="icon"><use href="#icon-activity"/></svg>Jakość kodeka (1–10)</label>
<input id="channel-codec-quality" name="codec_quality" type="number" min="1" max="10" placeholder="Domyślna serwera" value="{{.CodecQuality}}">
<small>Wyższa wartość oznacza lepszą jakość głosu, ale większe zużycie pasma.</small>
</div>
<button class="btn primary lg full" type="submit">
<svg class="icon"><use href="#icon-plus-circle"/></svg>Utwórz kanał i przenieś mnie
</button>
</form>
{{end}}
{{end}}
</div>
</div>
{{end}}
{{if .Client}}
<div class="client-badge">
<span class="online-dot" aria-hidden="true"></span>
<span>Wykryty klient</span>
<strong>{{.Client.Nick}}</strong>
</div>
<form method="post" action="/channel/create" class="channel-form">
<input type="hidden" name="form_token" value="{{.FormToken}}">
<input type="hidden" name="client_token" value="{{.ClientToken}}">
<div class="field">
<label for="channel-name">Nazwa kanału</label>
<input id="channel-name" name="name" maxlength="40" autocomplete="off" placeholder="Np. Pokój Mateusza">
<small>Pozostaw puste, aby wygenerować nazwę automatycznie.</small>
</div>
<div class="field">
<label for="channel-password">Hasło</label>
<input id="channel-password" name="password" maxlength="64" type="password" autocomplete="new-password" placeholder="Opcjonalne">
</div>
<div class="field">
<label for="channel-topic">Temat / opis</label>
<input id="channel-topic" name="topic" maxlength="255" autocomplete="off" placeholder="Opcjonalne">
</div>
<button class="btn btn-primary btn-large" type="submit">
Utwórz kanał i przenieś mnie</button>
</form>
{{end}}
{{end}}
</section>
</section>
</div>
</main>
</body>
</html>{{end}}