WIP: Vykuchano + zmena schematu.
This commit is contained in:
parent
eced140941
commit
128118ec36
523
app.php
523
app.php
|
@ -16,7 +16,7 @@ $singletons['rows'] = function(){
|
|||
|
||||
// HP & LOGIN
|
||||
route('', '/', function (){
|
||||
if (!user()) return redirect('/login/');
|
||||
// if (!user()) return redirect('/login/');
|
||||
return render('home');
|
||||
});
|
||||
|
||||
|
@ -89,528 +89,7 @@ route('', '/zmena-hesla/', function ($req){
|
|||
return render('form', ['form'=>$form, 'title'=>'Změnit heslo']);
|
||||
});
|
||||
|
||||
// SKLAD
|
||||
|
||||
route('GET', '/sklad/', function ($req){
|
||||
if (!user()) return redirect('/login/');
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
$items = $rows->page('items', ['is_active'=>1], ['ord'=>'asc']);
|
||||
|
||||
return render('items', ['items'=>$items]);
|
||||
});
|
||||
|
||||
$singletons['nabidka_form'] = function (){
|
||||
$form = new severak\forms\form(['method'=>'POST']);
|
||||
$form->field('name', ['required'=>true, 'label'=>'Název']);
|
||||
$form->field('price', ['type'=>'number', 'label'=>'Cena']);
|
||||
$form->field('note', ['type'=>'textarea', 'label'=>'Poznámka']);
|
||||
$form->field('ord', ['type'=>'number', 'label'=>'Pořadí']);
|
||||
$form->field('is_amount_tracked', ['type'=>'checkbox', 'label'=>'Hlídat počet na skladě?']);
|
||||
$form->field('amount', ['type'=>'number', 'label'=>'Počet na skladě']);
|
||||
$form->field('_save', ['type'=>'submit', 'label'=>'Přidat']);
|
||||
|
||||
$form->rule('price', function ($f){
|
||||
return $f > 0 || $f < 0;
|
||||
}, 'Cena nemůže být nulová.');
|
||||
|
||||
return $form;
|
||||
};
|
||||
|
||||
route('', '/sklad/pridat/', function ($req){
|
||||
if (!user()) return redirect('/login/');
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
/** @var severak\forms\form $form */
|
||||
$form = di('nabidka_form');
|
||||
|
||||
if ($req->getMethod()=='POST') {
|
||||
$form->fill($req->getParsedBody());
|
||||
if ($form->validate()) {
|
||||
$rows->insert('items', [
|
||||
'name'=>$form->values['name'],
|
||||
'price'=>$form->values['price'],
|
||||
'note'=>$form->values['note'],
|
||||
'ord'=>$form->values['ord'],
|
||||
'amount'=>$form->values['amount'],
|
||||
'is_amount_tracked'=>$form->values['is_amount_tracked'],
|
||||
]);
|
||||
return redirect('/sklad/');
|
||||
}
|
||||
}
|
||||
|
||||
return render('form', ['form'=>$form, 'title'=>'Přidat položku']);
|
||||
});
|
||||
|
||||
route('', '/sklad/upravit/{id}/', function ($req, $params){
|
||||
if (!user()) return redirect('/login/');
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
/** @var severak\forms\form $form */
|
||||
$form = di('nabidka_form');
|
||||
|
||||
$item = $rows->one('items', $params['id']);
|
||||
if (!$item) return notFound();
|
||||
$form->fill($item);
|
||||
|
||||
if ($req->getMethod()=='POST') {
|
||||
$form->fill($req->getParsedBody());
|
||||
if ($form->validate()) {
|
||||
$rows->update('items', [
|
||||
'name'=>$form->values['name'],
|
||||
'price'=>$form->values['price'],
|
||||
'note'=>$form->values['note'],
|
||||
'ord'=>$form->values['ord'],
|
||||
'amount'=>$form->values['amount'],
|
||||
'is_amount_tracked'=>$form->values['is_amount_tracked'],
|
||||
], $params['id']);
|
||||
return redirect('/sklad/');
|
||||
}
|
||||
}
|
||||
|
||||
return render('form', ['form'=>$form, 'title'=>'Upravit položku']);
|
||||
});
|
||||
|
||||
// TODO - tohle nechceme přes GET
|
||||
route('', '/sklad/smazat/{id}/', function ($req, $params){
|
||||
if (!user()) return redirect('/login/');
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
$rows->update('items', ['is_active'=>0], ['id'=>$params['id'] ]);
|
||||
return redirect('/sklad/');
|
||||
});
|
||||
|
||||
// ČLENOVÉ
|
||||
route('', '/clenove/', function ($req){
|
||||
if (!user()) return redirect('/login/');
|
||||
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
|
||||
if ($_POST['qrcode']) {
|
||||
$card = $rows->one('cards', ['id'=>$_POST['qrcode']]);
|
||||
if ($card) {
|
||||
return redirect('/clenove/detail/'. $card['member_id'] . '/');
|
||||
} else {
|
||||
flash('Karta není registrována.', 'error');
|
||||
return redirect('/clenove/');
|
||||
}
|
||||
}
|
||||
|
||||
$searchFor = $_GET['searchFor'] ?? null;
|
||||
$page = $_GET['page'] ?? 1;
|
||||
|
||||
if ($searchFor) {
|
||||
$searchSql = '%' . $searchFor . '%';
|
||||
$members = $rows->more('members', $rows->fragment('name LIKE ? OR email LIKE ? OR phone LIKE ?', [$searchSql, $searchSql, $searchSql]));
|
||||
$pages = 1;
|
||||
} else {
|
||||
$members = $rows->page('members', [], ['name'=>'asc'], $page, 30);
|
||||
$pages = $rows->pages;
|
||||
}
|
||||
|
||||
return render('members', ['members'=>$members, 'page'=>$page, 'pages'=>$pages, 'searchFor'=>$searchFor]);
|
||||
});
|
||||
|
||||
function items_sold(rows $rows, $od, $do) {
|
||||
$tsOd = strtotime($od);
|
||||
$tsDo = strtotime($do);
|
||||
|
||||
return $rows->execute($rows->query('SELECT item_id, SUM(amount) AS amount FROM sold_items WHERE date>? AND date<?', [$tsOd, $tsDo]))->fetchAll(PDO::FETCH_KEY_PAIR);
|
||||
}
|
||||
|
||||
route('', '/sklad/prodano/', function ($req){
|
||||
if (!user()) return redirect('/login/');
|
||||
$user = user();
|
||||
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
|
||||
$this_week = items_sold($rows, 'monday this week', 'now');
|
||||
$last_week = items_sold($rows, 'monday last week', 'sunday last week +24 hours -1 sec');
|
||||
$this_month = items_sold($rows, 'first day of this month midnight', 'last day of this month midnight +24 hours -1 sec');
|
||||
$last_month = items_sold($rows, 'first day of last month midnight', 'last day of last month midnight +24 hours -1 sec');
|
||||
|
||||
$items = $rows->page('items', ['is_active'=>1, 'is_amount_tracked'=>1], ['ord'=>'asc']);
|
||||
return render('items_sold', ['items'=>$items, 'this_week'=>$this_week, 'last_week'=>$last_week, 'this_month'=>$this_month, 'last_month'=>$last_month]);
|
||||
});
|
||||
|
||||
|
||||
route('', '/clenove/pridat/', function ($req){
|
||||
if (!user()) return redirect('/login/');
|
||||
$user = user();
|
||||
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
|
||||
$form = new severak\forms\form(['method'=>'POST']);
|
||||
$form->field('card_id', ['required'=>true, 'type'=>'number', 'label'=>'Číslo karty', 'id'=>'qrcode']);
|
||||
$form->field('name', ['required'=>true, 'label'=>'Jméno']);
|
||||
$form->field('email', ['type'=>'email', 'label'=>'E-mail']);
|
||||
$form->field('phone', ['type'=>'phone', 'label'=>'Telefon']);
|
||||
$form->field('date_of_birth', ['type'=>'date', 'label'=>'Datum narození']);
|
||||
|
||||
$form->field('_save', ['type'=>'submit', 'label'=>'Přidat']);
|
||||
|
||||
if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody()) && $form->validate()) {
|
||||
|
||||
$card = $rows->one('cards', $form->values['card_id']);
|
||||
if ($card) {
|
||||
$form->error('card_id', 'Karta již je registrovaná v systému!');
|
||||
}
|
||||
|
||||
// TODO - tyhle duplikáty řešit jinak
|
||||
if ($rows->one('members', ['name'=>$form->values['name']])) {
|
||||
$form->error('name', 'Tento člen již kartičku má!');
|
||||
}
|
||||
|
||||
if (!empty($form->values['email']) && $rows->one('members', ['email'=>$form->values['email']])) {
|
||||
$form->error('email', 'Tento email již má některý člen.');
|
||||
}
|
||||
|
||||
if (!empty($form->values['phone']) && $rows->one('members', ['phone'=>$form->values['phone']])) {
|
||||
$form->error('phone', 'Tento telefon již má některý člen.!');
|
||||
}
|
||||
|
||||
if ($form->isValid) {
|
||||
$memberId = $rows->insert('members', [
|
||||
'name'=>$form->values['name'],
|
||||
'email'=>$form->values['email'],
|
||||
'phone'=>$form->values['phone'],
|
||||
'date_of_birth'=>$form->values['date_of_birth'],
|
||||
]);
|
||||
|
||||
$rows->insert('cards', [
|
||||
'id'=>$form->values['card_id'],
|
||||
'member_id'=>$memberId,
|
||||
'issued_by'=>$user['id'],
|
||||
'issued_at'=>time(),
|
||||
'is_active'=>1
|
||||
]);
|
||||
|
||||
flash('Člen byl úspěšně registrován.');
|
||||
return redirect('/');
|
||||
}
|
||||
}
|
||||
|
||||
return render('form', ['form'=>$form, 'title'=>'Přidat člena']);
|
||||
});
|
||||
|
||||
route('', '/clenove/detail/{id}/', function ($req, $params) {
|
||||
if (!user()) return redirect('/login/');
|
||||
$user = user();
|
||||
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
|
||||
$member = $rows->one('members', $params['id']);
|
||||
if (!$member) return notFound();
|
||||
|
||||
$page = $_GET['page'] ?? 1;
|
||||
|
||||
$transactions = $rows->page('transactions', ['member_id'=>$params['id']], ['issued_at'=>'desc'], $page, 30);
|
||||
$cards = $rows->more('cards', ['member_id'=>$params['id']], ['issued_at'=>'desc']);
|
||||
$pages = $rows->pages;
|
||||
|
||||
return render('member_detail', ['member'=>$member, 'page'=>$page, 'pages'=>$pages, 'transactions'=>$transactions, 'cards'=>$cards]);
|
||||
});
|
||||
|
||||
route('', '/clenove/upravit/{id}/', function ($req, $params) {
|
||||
if (!user()) return redirect('/login/');
|
||||
$user = user();
|
||||
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
|
||||
$member = $rows->one('members', $params['id']);
|
||||
if (!$member) return notFound();
|
||||
|
||||
$form = new severak\forms\form(['method'=>'POST']);
|
||||
$form->field('name', ['required'=>true, 'label'=>'Jméno']);
|
||||
$form->field('email', ['type'=>'email', 'label'=>'E-mail']);
|
||||
$form->field('phone', ['type'=>'phone', 'label'=>'Telefon']);
|
||||
$form->field('date_of_birth', ['type'=>'date', 'label'=>'Datum narození']);
|
||||
$form->field('note', ['type'=>'textarea', 'rows'=>3, 'label'=>'Poznámka']);
|
||||
$form->field('is_active', ['type'=>'checkbox', 'label'=>'Je aktivní?']);
|
||||
|
||||
$form->field('_save', ['type'=>'submit', 'label'=>'Upravit']);
|
||||
|
||||
$form->fill($member);
|
||||
|
||||
if ($req->getMethod()=='POST') {
|
||||
$form->fill($req->getParsedBody());
|
||||
|
||||
// TODO - zde nějak ošetřovat duplicity
|
||||
|
||||
if ($form->validate()) {
|
||||
$rows->update('members', [
|
||||
'name'=>$form->values['name'],
|
||||
'email'=>$form->values['email'],
|
||||
'phone'=>$form->values['phone'],
|
||||
'date_of_birth'=>$form->values['date_of_birth'],
|
||||
'note'=>$form->values['note'],
|
||||
'is_active'=>$form->values['is_active'] ?? 0,
|
||||
], $params['id']);
|
||||
|
||||
if (!$form->values['is_active']) {
|
||||
// deaktivujeme kartičku
|
||||
$rows->update('cards', ['is_active'=>0, 'note'=>'deaktivována s uživatelem'], ['is_active'=>'1', 'member_id'=>$params['id']]);
|
||||
}
|
||||
|
||||
if (!$member['is_active'] && $form->values['is_active']) {
|
||||
flash('Nyní musíte vystavit novou kartičku.', 'warning');
|
||||
}
|
||||
|
||||
return redirect('/clenove/detail/'. $params['id'].'/');
|
||||
}
|
||||
}
|
||||
|
||||
return render('form', ['form'=>$form, 'title'=>'Upravit člena']);
|
||||
});
|
||||
|
||||
route('', '/clenove/nova_karta/{id}/', function ($req, $params) {
|
||||
if (!user()) return redirect('/login/');
|
||||
$user = user();
|
||||
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
|
||||
$member = $rows->one('members', $params['id']);
|
||||
if (!$member) return notFound();
|
||||
|
||||
$reasons = [
|
||||
'ztracená' => 'karta byla ztracená',
|
||||
'ukradená' => 'karta byla ukradená',
|
||||
'obnovení členství' => 'obnovení členství'
|
||||
];
|
||||
|
||||
$form = new severak\forms\form(['method'=>'POST']);
|
||||
$form->field('card_id', ['required'=>true, 'type'=>'number', 'label'=>'Číslo karty', 'id'=>'qrcode']);
|
||||
$form->field('reason', ['type'=>'select', 'label'=>'Důvod vydání nové karty', 'options'=>$reasons]);
|
||||
$form->field('block_original', ['type'=>'checkbox', 'label'=>'zablokovat původní kartu']);
|
||||
|
||||
$form->field('_save', ['type'=>'submit', 'label'=>'Vystavit novou kartu']);
|
||||
|
||||
if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody()) && $form->validate()) {
|
||||
|
||||
$card = $rows->one('cards', $form->values['card_id']);
|
||||
if ($card) {
|
||||
$form->error('card_id', 'Karta již je registrovaná v systému!');
|
||||
}
|
||||
$form->fill($req->getParsedBody());
|
||||
|
||||
if ($form->validate()) {
|
||||
// deaktivujeme původní kartu
|
||||
$rows->update('cards', [
|
||||
'is_active' => 0,
|
||||
'is_blocked' => $form->values['block_original'] ?? 0,
|
||||
'note' => $form->values['reason']
|
||||
], ['is_active' => '1', 'member_id' => $params['id']]);
|
||||
|
||||
// přidáváme novou
|
||||
$rows->insert('cards', [
|
||||
'id'=>$form->values['card_id'],
|
||||
'member_id'=>$params['id'],
|
||||
'issued_by'=>$user['id'],
|
||||
'issued_at'=>time(),
|
||||
'is_active'=>1
|
||||
]);
|
||||
|
||||
return redirect('/clenove/detail/'. $params['id'].'/');
|
||||
}
|
||||
}
|
||||
|
||||
return render('form', ['form'=>$form, 'title'=>'Nová karta']);
|
||||
});
|
||||
|
||||
// POKLADNA:
|
||||
route('','/pokladna/', function(){
|
||||
return render('pokladna', ['title'=>'pokladna']);
|
||||
});
|
||||
|
||||
route('', '/pokladna/dobit/', function ($req){
|
||||
if (!user()) return redirect('/login/');
|
||||
$user = user();
|
||||
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
|
||||
$form = new form(['method'=>'post']);
|
||||
$form->field('card_id', ['required'=>true, 'type'=>'number', 'label'=>'Číslo karty', 'id'=>'qrcode']);
|
||||
$form->field('amount', ['required'=>true, 'type'=>'number', 'label'=>'Částka']);
|
||||
$form->field('_sbt', ['label'=>'Vložit', 'type'=>'submit']);
|
||||
|
||||
// TODO - zde kontrolovat maxmální a minimální výši nabití
|
||||
|
||||
if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody()) && $form->validate()) {
|
||||
$card = $rows->one('cards', ['id'=>$form->values['card_id']]);
|
||||
|
||||
if (!$card || !$card['is_active']) {
|
||||
$form->error('card_id', 'Neznámá/neplatná karta!');
|
||||
}
|
||||
|
||||
if ($card && $card['is_blocked']) {
|
||||
$form->error('card_id', 'Karta je zablokovaná.');
|
||||
}
|
||||
|
||||
if ($card) {
|
||||
$member = $rows->one('members', $card['member_id']);
|
||||
}
|
||||
|
||||
if ($form->isValid) {
|
||||
// BIG TODO - tohle dělat v databázové transakci
|
||||
$rows->insert('transactions', [
|
||||
'member_id' => $member['id'],
|
||||
'card_id' => $card['id'],
|
||||
'issued_by'=>$user['id'],
|
||||
'issued_at'=>time(),
|
||||
'amount'=>$form->values['amount'],
|
||||
'is_cash'=>1
|
||||
]);
|
||||
|
||||
$rows->execute($rows->query('UPDATE members SET balance = balance + ? WHERE id=?', [$form->values['amount'], $member['id']]));
|
||||
|
||||
flash('Kredit úspěšně dobit!', 'success');
|
||||
|
||||
return redirect('/');
|
||||
}
|
||||
}
|
||||
return render('form', ['form'=>$form, 'title'=>'Dobít kartu']);
|
||||
});
|
||||
|
||||
// TODO - zůstatek, vybrat
|
||||
|
||||
// BAR:
|
||||
|
||||
route('GET', '/bar/', function ($req){
|
||||
if (!user()) return redirect('/login/');
|
||||
$user = user();
|
||||
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
$nabidka = $rows->more('items', ['is_active'=>1], ['ord'=>'asc']);
|
||||
|
||||
return render('bar', ['items'=>$nabidka]);
|
||||
});
|
||||
|
||||
route('POST', '/bar/userinfo/', function ($req){
|
||||
if (!user()) return jsonResponse(['error'=>'Unauthorized.'], 403);
|
||||
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
|
||||
$Q = $req->getParsedBody();
|
||||
|
||||
if (empty($Q['card_id'])) {
|
||||
return jsonResponse(['error'=>'Špatný formát čísla karty.']);
|
||||
}
|
||||
|
||||
$card = $rows->one('cards', $Q['card_id']);
|
||||
|
||||
if ($card && $card['is_blocked']) {
|
||||
return jsonResponse(['error'=>'Karta je zablokovaná.']);
|
||||
}
|
||||
|
||||
if (!$card || !$card['is_active']) {
|
||||
return jsonResponse(['error'=>'Karta není aktivní.']);
|
||||
}
|
||||
|
||||
$member = $rows->one('members', $card['member_id']);
|
||||
|
||||
if ($member['balance']==0) {
|
||||
return jsonResponse(['error'=>'Karta není nabitá.']);
|
||||
}
|
||||
|
||||
$dobMember = date_create($member['date_of_birth']);
|
||||
$before18Years = date_create('now - 18 years');
|
||||
|
||||
$canBuyAlcohol = $dobMember && ($dobMember < $before18Years);
|
||||
|
||||
return jsonResponse([
|
||||
'name' => $member['name'],
|
||||
'balance' => $member['balance'],
|
||||
'can_buy_alcohol' => $canBuyAlcohol,
|
||||
]);
|
||||
});
|
||||
|
||||
route('POST', '/bar/buy/', function ($req){
|
||||
if (!user()) return jsonResponse(['error'=>'Vypršelo přihlášení.']);
|
||||
$user = user();
|
||||
|
||||
/** @var Psr\Http\Message\ServerRequestInterface $req */
|
||||
/** @var severak\database\rows $rows */
|
||||
$rows = di('rows');
|
||||
|
||||
$Q = $req->getParsedBody();
|
||||
|
||||
if (empty($Q['card_id'])) {
|
||||
return jsonResponse(['error'=>'Špatný formát čísla karty.']);
|
||||
}
|
||||
|
||||
$card = $rows->one('cards', $Q['card_id']);
|
||||
|
||||
if ($card && $card['is_blocked']) {
|
||||
return jsonResponse(['error'=>'Karta je zablokovaná.']);
|
||||
}
|
||||
|
||||
if (!$card || !$card['is_active']) {
|
||||
return jsonResponse(['error'=>'Karta není aktivní.']);
|
||||
}
|
||||
|
||||
$member = $rows->one('members', $card['member_id']);
|
||||
|
||||
if ($member['balance']<1) {
|
||||
return jsonResponse(['error'=>'Karta není nabitá.']);
|
||||
}
|
||||
|
||||
$totalSum = 0;
|
||||
foreach ($Q['items'] as $item) {
|
||||
$totalSum = $totalSum + ($item['price'] * $item['amount']);
|
||||
}
|
||||
|
||||
if ($member['balance']<$totalSum) {
|
||||
return jsonResponse(['error'=>'Na kartě není dostatek peněz.', 'balance'=>$member['balance']]);
|
||||
}
|
||||
|
||||
$transcactionId = $rows->insert('transactions', [
|
||||
'member_id' => $member['id'],
|
||||
'card_id' => $card['id'],
|
||||
'issued_by'=>$user['id'],
|
||||
'issued_at'=>time(),
|
||||
'amount'=>$totalSum * -1,
|
||||
'items' => json_encode($Q['items']),
|
||||
'is_cash'=>0
|
||||
]);
|
||||
|
||||
$rows->execute($rows->query('UPDATE members SET balance = balance - ? WHERE id=?', [$totalSum, $member['id']]));
|
||||
|
||||
$isAmountTracked = array_column($rows->more('items'), 'is_amount_tracked', 'id');
|
||||
|
||||
foreach ($Q['items'] as $item) {
|
||||
if ($item['id'] && $isAmountTracked[$item['id']]) {
|
||||
$rows->insert('sold_items', [
|
||||
'item_id' => $item['id'],
|
||||
'transaction_id' => $transcactionId,
|
||||
'amount' => $item['amount'],
|
||||
'date'=>time()
|
||||
]);
|
||||
$rows->execute($rows->query('UPDATE items SET amount=amount-1 WHERE id=?', [$item['id']]));
|
||||
}
|
||||
}
|
||||
|
||||
return jsonResponse(['success'=>true]);
|
||||
});
|
||||
|
||||
// OBSLUHA
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
// path to database
|
||||
$config['database'] = 'db/stela.sqlite';
|
||||
$config['database'] = 'db/pruvodce.sqlite';
|
||||
// MD5 of adminer password
|
||||
$config['adminer_password'] = md5('heslo');
|
||||
// secret key (throw something from random.org here)
|
||||
|
|
|
@ -1,4 +1,22 @@
|
|||
|
||||
-- Adminer 4.7.5 SQLite 3 dump
|
||||
|
||||
CREATE TABLE "poi" (
|
||||
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"slug" text NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"description" text NOT NULL,
|
||||
"cheatsheet" text NOT NULL,
|
||||
"internal" text NOT NULL,
|
||||
"is_public" integer NOT NULL DEFAULT '0'
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "poi_slug" ON "poi" ("slug");
|
||||
|
||||
|
||||
CREATE TABLE sqlite_sequence(name,seq);
|
||||
|
||||
INSERT INTO "sqlite_sequence" ("name", "seq") VALUES ('users', 1);
|
||||
|
||||
CREATE TABLE "users" (
|
||||
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
|
@ -13,5 +31,6 @@ CREATE TABLE "users" (
|
|||
|
||||
CREATE UNIQUE INDEX "users_usename" ON "users" ("username");
|
||||
|
||||
INSERT INTO "users" ("id", "username", "password", "name", "note", "is_active", "is_superuser") VALUES (1, 'severak', '$2y$10$G//hwvWHJYNHFk6JNr3GG.kuzM/dI9UTtU2bxr9EvTTEg0YOc8mj.', 'Severák', '(testovací účet)', 1,1);
|
||||
INSERT INTO "users" ("id", "member_id", "username", "password", "name", "note", "is_active", "is_superuser") VALUES (1, NULL, 'severak', '$2y$10$G//hwvWHJYNHFk6JNr3GG.kuzM/dI9UTtU2bxr9EvTTEg0YOc8mj.', 'Severák', '(testovací účet)', 1, 1);
|
||||
|
||||
--
|
||||
|
|
133
tpl/_footer.php
133
tpl/_footer.php
|
@ -1,136 +1,5 @@
|
|||
</main>
|
||||
</div>
|
||||
</section>
|
||||
<section class="section" id="qrscanner" style="display: none">
|
||||
<div class="container" style="max-width: 800px">
|
||||
<div id="qr_loadingMessage">🎥 Unable to access video stream (please make sure you have a webcam enabled)</div>
|
||||
<div style="max-width: 100%">
|
||||
<canvas id="qr_canvas" hidden style="max-width: 100%"></canvas>
|
||||
</div>
|
||||
<div id="qr_output" hidden>
|
||||
<div id="qr_outputMessage">No QR code detected.</div>
|
||||
<div hidden><b>Data:</b> <span id="qr_outputData"></span></div>
|
||||
</div>
|
||||
<a href="#" id="qr_manual" class="button is-fullwidth">zadat QR kód ručně</a>
|
||||
</div>
|
||||
</section>
|
||||
<script src="/static/uboot.js"></script>
|
||||
<script>
|
||||
whenReady(function () {
|
||||
on('navbar-burger', 'click', function () {
|
||||
if (hasClass('navbar-burger', 'is-active')) {
|
||||
delClass('navbar-burger', 'is-active');
|
||||
delClass('navbar-menu', 'is-active');
|
||||
} else {
|
||||
addClass('navbar-burger', 'is-active');
|
||||
addClass('navbar-menu', 'is-active');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script src="/static/jsQR.js"></script>
|
||||
<script>
|
||||
whenReady(function () {
|
||||
var video = document.createElement("video");
|
||||
var canvasElement = document.getElementById("qr_canvas");
|
||||
var canvas = canvasElement.getContext("2d");
|
||||
var loadingMessage = document.getElementById("qr_loadingMessage");
|
||||
var outputContainer = document.getElementById("qr_output");
|
||||
var outputMessage = document.getElementById("qr_outputMessage");
|
||||
var outputData = document.getElementById("qr_outputData");
|
||||
var localstream;
|
||||
|
||||
function videoOff() {
|
||||
//clearInterval(theDrawLoop);
|
||||
//ExtensionData.vidStatus = 'off';
|
||||
video.pause();
|
||||
video.src = "";
|
||||
if (localstream) localstream.getTracks()[0].stop();
|
||||
//console.log("Vid off");
|
||||
}
|
||||
|
||||
function drawLine(begin, end, color) {
|
||||
canvas.beginPath();
|
||||
canvas.moveTo(begin.x, begin.y);
|
||||
canvas.lineTo(end.x, end.y);
|
||||
canvas.lineWidth = 4;
|
||||
canvas.strokeStyle = color;
|
||||
canvas.stroke();
|
||||
}
|
||||
|
||||
function tick() {
|
||||
loadingMessage.innerText = "⌛ Loading video..."
|
||||
if (video.readyState === video.HAVE_ENOUGH_DATA) {
|
||||
loadingMessage.hidden = true;
|
||||
canvasElement.hidden = false;
|
||||
outputContainer.hidden = false;
|
||||
|
||||
canvasElement.height = video.videoHeight;
|
||||
canvasElement.width = video.videoWidth;
|
||||
canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
|
||||
var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
|
||||
var code = jsQR(imageData.data, imageData.width, imageData.height, {
|
||||
inversionAttempts: "dontInvert",
|
||||
});
|
||||
if (code) {
|
||||
drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
|
||||
drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
|
||||
drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
|
||||
drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
|
||||
outputMessage.hidden = true;
|
||||
outputData.parentElement.hidden = false;
|
||||
outputData.innerText = code.data;
|
||||
|
||||
gebi('qrcode').value = code.data;
|
||||
gebi('app').style.display = 'block';
|
||||
gebi('qrscanner').style.display = 'none';
|
||||
|
||||
videoOff();
|
||||
return;
|
||||
|
||||
} else {
|
||||
outputMessage.hidden = false;
|
||||
outputData.parentElement.hidden = true;
|
||||
}
|
||||
}
|
||||
requestAnimationFrame(tick);
|
||||
}
|
||||
|
||||
if (gebi('qrcode')) {
|
||||
on('qrcode', 'click', function (event) {
|
||||
// schovame app a odkryjem QR scanner
|
||||
gebi('app').style.display = 'none';
|
||||
gebi('qrscanner').style.display = 'block';
|
||||
|
||||
// Use facingMode: environment to attemt to get the front camera on phones
|
||||
navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then(function(stream) {
|
||||
video.srcObject = stream;
|
||||
localstream = stream;
|
||||
video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
|
||||
video.play();
|
||||
requestAnimationFrame(tick);
|
||||
}).catch(function () {
|
||||
gebi('app').style.display = 'block';
|
||||
gebi('qrscanner').style.display = 'none';
|
||||
gebi('qrcode').focus();
|
||||
videoOff();
|
||||
});
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
on('qr_manual', 'click', function (event) {
|
||||
gebi('app').style.display = 'block';
|
||||
gebi('qrscanner').style.display = 'none';
|
||||
gebi('qrcode').focus();
|
||||
videoOff();
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title><?php if (isset($title)) echo $title . ' - ' ; ?>Stela</title>
|
||||
<title><?php if (isset($title)) echo $title . ' - ' ; ?>Průvodce</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css">
|
||||
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
|
||||
<script src="/static/vue.min.js"></script>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||
|
@ -17,7 +16,7 @@
|
|||
<div class="container" style="max-width: 800px">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="/">
|
||||
Stela <img src="/favicon-32x32.png">
|
||||
Průvodce <img src="/favicon-32x32.png">
|
||||
</a>
|
||||
|
||||
<a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample" id="navbar-burger">
|
||||
|
@ -30,21 +29,6 @@
|
|||
<div id="navbar-menu" class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
<?php if (user()) { ?>
|
||||
<a class="navbar-item" href="/bar/">
|
||||
bar
|
||||
</a>
|
||||
|
||||
<a class="navbar-item" href="/pokladna/">
|
||||
pokladna
|
||||
</a>
|
||||
|
||||
<a class="navbar-item" href="/sklad/">
|
||||
sklad
|
||||
</a>
|
||||
|
||||
<a class="navbar-item" href="/clenove/">
|
||||
členové
|
||||
</a>
|
||||
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link">
|
||||
|
@ -91,4 +75,4 @@
|
|||
}
|
||||
}
|
||||
?>
|
||||
<main>
|
||||
<main>
|
||||
|
|
239
tpl/bar.php
239
tpl/bar.php
|
@ -1,239 +0,0 @@
|
|||
<?=render('_header', ['title'=>$title ?? null]); ?>
|
||||
<div id="barapp" >
|
||||
|
||||
<!-- nejdříve se přihlásíme přes https://cozmo.github.io/jsQR/ -->
|
||||
|
||||
<div class="message is-success" v-show="success && !name">
|
||||
<div class="message-body">
|
||||
Nákup proběhl úspěšně. Můžete zadat další.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field has-addons" v-show="!name">
|
||||
<div class="control is-expanded">
|
||||
<input name="searchFor" class="input" placeholder="číslo karty" v-model="card_id" @change="findUser" id="qrcode">
|
||||
</div>
|
||||
<div class="control">
|
||||
<input type="submit" class="button is-info" value="přihlásit" @click="findUser">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="message is-danger" v-show="!name && error">
|
||||
<div class="message-body">
|
||||
{{ error }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="name">
|
||||
<div class="message" >
|
||||
<div class="message-body">
|
||||
<div class="columns is-mobile">
|
||||
<div class="column"><span class="fas fa-user"></span>
|
||||
{{ name }}</div>
|
||||
<div class="column has-text-right">{{ balance }},-</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="message is-danger" v-show="!can_buy_alcohol">
|
||||
<div class="message-body">
|
||||
Pod 18 let - neprodávat alkohol!
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table" v-show="items.length">
|
||||
|
||||
<tr>
|
||||
<th>název</th>
|
||||
<th>/kus</th>
|
||||
<th>počet</th>
|
||||
<th>součet</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
|
||||
<tr v-for="item in items" class="is-vcentered">
|
||||
<td><input name="item[]" class="input is-static" placeholder="název zboží" v-model="item.name"></td>
|
||||
<td><input name="price[]" inputmode="numeric" class="input is-static" v-model="item.price"></td>
|
||||
<td><input name="amount[]" type="number" min="1" max="100" class="input is-static" v-model="item.amount"></td>
|
||||
<td class="has-text-right"><div class="input is-static">{{ item.price * item.amount }}</div></td>
|
||||
<td><div class="input is-static"><a class="delete" @click="removeItem(item)"></a></div></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th colspan="3">celkem</th>
|
||||
<th v-bind:class="totalClass" class="has-text-right">{{ totalAmount }}</th>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<div class="message is-danger" v-show="error">
|
||||
<div class="message-body">
|
||||
{{ error }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="columns is-mobile">
|
||||
<div class="column">
|
||||
<button class="button is-light" @click="addItem">Přidat položku</button>
|
||||
</div>
|
||||
<div class="column has-text-right">
|
||||
<input type="submit" value="Uložit" class="button is-primary" v-show="items.length" @click="completePurchase">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="buttons">
|
||||
<?php foreach ($items as $item) {
|
||||
$warning = $item['price']<0 ? 'has-background-warning' : '';
|
||||
?>
|
||||
<button class="button is-fullwidth <?=$warning; ?>" @click="addPredefined" data-id="<?=$item['id']; ?>" data-name="<?=$item['name']; ?>" data-price="<?=$item['price']; ?>"><?=$item['name']; ?></button>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
function sendData(url, data, onsuccess, onerror) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', url);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
var response = JSON.parse(xhr.responseText);
|
||||
onsuccess(response);
|
||||
} else {
|
||||
onerror();
|
||||
}
|
||||
};
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
var app = new Vue({
|
||||
el: '#barapp',
|
||||
data: {
|
||||
card_id: null,
|
||||
name: null,
|
||||
balance: -1,
|
||||
can_buy_alcohol: false,
|
||||
items : [],
|
||||
error: false,
|
||||
success: false
|
||||
},
|
||||
|
||||
computed: {
|
||||
totalAmount: function()
|
||||
{
|
||||
var total = 0;
|
||||
this.items.forEach(function (item) {
|
||||
total += item.price * item.amount;
|
||||
});
|
||||
return total;
|
||||
},
|
||||
|
||||
totalClass: function () {
|
||||
return {
|
||||
'has-text-danger': this.totalAmount > this.balance
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
reset: function() {
|
||||
this.card_id= null;
|
||||
this.name= null;
|
||||
this.balance= -1;
|
||||
this.can_buy_alcohol= false;
|
||||
this.items = [];
|
||||
this.error= false;
|
||||
},
|
||||
|
||||
findUser: function(ev) {
|
||||
var that = this;
|
||||
|
||||
// TODO - z nějakého důvodu se nepropisů QR kódy ze čtečky
|
||||
that.card_id = gebi('qrcode').value;
|
||||
|
||||
sendData('/bar/userinfo/', {card_id: that.card_id}, function (response) {
|
||||
if (response.error) {
|
||||
that.error = response.error;
|
||||
} else if (response.name) {
|
||||
that.name = response.name;
|
||||
that.balance = response.balance;
|
||||
that.can_buy_alcohol = response.can_buy_alcohol;
|
||||
that.items = [];
|
||||
that.error = false;
|
||||
}
|
||||
}, function () {
|
||||
that.error = 'Došlo k nečekané chybě.';
|
||||
});
|
||||
},
|
||||
|
||||
addPredefined: function(ev) {
|
||||
var name = ev.target.getAttribute('data-name');
|
||||
var price = ev.target.getAttribute('data-price');
|
||||
var id = ev.target.getAttribute('data-id');
|
||||
var alreadyThere = false;
|
||||
this.items.forEach(function (item) {
|
||||
if (item.id && item.id==id) {
|
||||
item.amount++;
|
||||
alreadyThere = true;
|
||||
}
|
||||
});
|
||||
if (alreadyThere) return;
|
||||
|
||||
this.items.push({
|
||||
name: name,
|
||||
price: price,
|
||||
amount: 1,
|
||||
total: price,
|
||||
id: id
|
||||
});
|
||||
},
|
||||
|
||||
addItem: function(){
|
||||
this.items.push({
|
||||
name: "",
|
||||
price: 0,
|
||||
amount: 1,
|
||||
total: 0
|
||||
});
|
||||
},
|
||||
|
||||
changedItem: function(item) {
|
||||
item.total = item.price * item.amount;
|
||||
},
|
||||
|
||||
removeItem: function (item) {
|
||||
if (item.amount>1) {
|
||||
item.amount -= 1;
|
||||
return;
|
||||
}
|
||||
this.items.splice(this.items.indexOf(item), 1)
|
||||
},
|
||||
|
||||
completePurchase: function () {
|
||||
var that = this;
|
||||
|
||||
sendData('/bar/buy/', {card_id: that.card_id, items: that.items}, function (response) {
|
||||
if (response.error) {
|
||||
that.error = response.error;
|
||||
if (response.balance) {
|
||||
that.balance = response.balance;
|
||||
}
|
||||
} else if (response.success) {
|
||||
that.success = true;
|
||||
that.reset();
|
||||
}
|
||||
}, function () {
|
||||
that.error = 'Došlo k nečekané chybě.';
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.app = app;
|
||||
</script>
|
||||
<?=render('_footer');?>
|
|
@ -1,9 +1,5 @@
|
|||
<?= render('_header'); ?>
|
||||
|
||||
<div class="buttons">
|
||||
<a href="/bar/" class="button is-fullwidth is-primary">zaplatit na baru</a>
|
||||
<a href="/pokladna/dobit/" class="button is-fullwidth">dobít kredit</a>
|
||||
<a href="/clenove/pridat/" class="button is-fullwidth">přidat člena</a>
|
||||
</div>
|
||||
<p>TODO</p>
|
||||
|
||||
<?= render('_footer'); ?>
|
||||
<?= render('_footer'); ?>
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
<?=render('_header', ['title'=>'Sklad / stálé položky']);?>
|
||||
|
||||
<h1>Sklad <small>/ stálé položky</small></h1>
|
||||
|
||||
<?php if (count($items)) { ?>
|
||||
<table class="table">
|
||||
<tr><th>název</th><th>cena</th><th>počet</th><th></th><th></th></tr>
|
||||
<?php foreach ($items as $item) { ?>
|
||||
<tr>
|
||||
<td><?=$item['name']; ?><br><small><?=$item['note']; ?></small></td>
|
||||
<td><?=$item['price']; ?>,-</td>
|
||||
<td class="has-text-right">
|
||||
<?php
|
||||
$class = 'is-success is-light';
|
||||
if ($item['amount']<5) $class = 'is-danger';
|
||||
if ($item['amount']>4 && $item['amount']<10) $class = 'is-warning';
|
||||
if ($item['is_amount_tracked']) {
|
||||
?>
|
||||
<span class="tag <?=$class; ?>"><?=$item['amount']; ?></span>
|
||||
<?php } else { ?>
|
||||
---
|
||||
<?php } ?>
|
||||
</td>
|
||||
<td><a href="/sklad/upravit/<?=$item['id']; ?>/" class=""><span class="icon"><i class="fas fa-edit"></i></span></a> </td>
|
||||
<td><a href="/sklad/smazat/<?=$item['id']; ?>/" class="delete" onclick="return confirm('Opravdu chcete položku smazat?')">smazat</a> </td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table>
|
||||
<?php } else {
|
||||
echo '<p>(nenalezeny žádné položky)</p><br>';
|
||||
} ?>
|
||||
|
||||
<a href="/sklad/pridat/" class="button is-primary">Přidat položku</a>
|
||||
|
||||
<br><br>
|
||||
<a href="/sklad/prodano/" class="button">Prodané položky</a>
|
||||
|
||||
<?=render('_footer');?>
|
|
@ -1,21 +0,0 @@
|
|||
<?= render('_header', ['title'=>'Prodané položky']); ?>
|
||||
|
||||
<h1>Prodané položky</h1>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr><th>název</th><th>tento týden</th><th>minulý týden</th><th>tento měsíc</th><th>minulý měsíc</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($items as $item) { $item_id =$item['id']; ?>
|
||||
<tr><td><?=$item['name']; ?></td><td><?=$this_week[$item_id] ?? ''; ?></td><td><?=$last_week[$item_id] ?? ''; ?></td><td><?=$this_month[$item_id] ?? ''; ?></td><td><?=$last_month[$item_id] ?? ''; ?></td></tr>
|
||||
<?php } ?>
|
||||
|
||||
<?php if (empty($items)) { ?>
|
||||
<tr><td colspan="5"><em>žádné </em></td></tr>
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?= render('_footer'); ?>
|
|
@ -1,83 +0,0 @@
|
|||
<?=render('_header', ['title'=>'detail člena']);?>
|
||||
|
||||
<div class="message" >
|
||||
<div class="message-header">Detail člena</div>
|
||||
<div class="message-body">
|
||||
<div class="columns is-mobile">
|
||||
<div class="column">
|
||||
<?php if (!$member['is_active']) { ?><span class="tag is-warning">neaktivní</span> <?php } ?>
|
||||
<span class="icon"><span class="icon fas fa-user"></span></span><?=$member['name']; ?></div>
|
||||
<div class="column has-text-right"><?=$member['balance']; ?>,-</div>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<?php if ($member['phone']) { ?>
|
||||
<span class="icon"><span class="icon fas fa-phone"></span></span><?=$member['phone']; ?>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<div class="column has-text-right">
|
||||
<?php if ($member['email']) { ?>
|
||||
<span class="icon"><span class="fas fa-envelope"></span></span><?=$member['email']; ?>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<u>karty:</u>
|
||||
<ul><?php
|
||||
foreach ($cards as $card) {
|
||||
echo '<li>';
|
||||
if ($card['is_active']) echo '<strong>';
|
||||
|
||||
echo $card['id']. ' <em>' . $card['note'] . '</em>';
|
||||
|
||||
if ($card['is_active']) echo '</strong>';
|
||||
echo '</li>';
|
||||
} ?>
|
||||
</ul>
|
||||
|
||||
<p><?=$member['note']; ?></p>
|
||||
</div>
|
||||
<a href="/clenove/upravit/<?=$member['id']; ?>/" class="button">upravit</a>
|
||||
<a href="/clenove/nova_karta/<?=$member['id']; ?>/" class="button">vystavit novou kartu</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (count($transactions)) { ?>
|
||||
|
||||
<h2 class="subtitle">poslední provedené transakce</h2>
|
||||
|
||||
<table class="table">
|
||||
<tr><th>čas</th><th>částka</th><th></th><th></th></tr>
|
||||
<?php foreach ($transactions as $tsx) {
|
||||
$datum = date_create('@'.$tsx['issued_at']);
|
||||
?>
|
||||
<tr>
|
||||
<td><?=$datum ? $datum->format('j.n.Y H:i') : ''; ?></td>
|
||||
<td><?=$tsx['amount']; ?>,-</td>
|
||||
<td>
|
||||
|
||||
|
||||
<?php if ($tsx['is_cash']) {
|
||||
echo 'dobytí';
|
||||
} else if (json_decode($tsx['items'])) {
|
||||
echo '<details><summary>nákup</summary><ul>';
|
||||
$items = json_decode($tsx['items'], true);
|
||||
foreach ($items as $item) {
|
||||
echo '<li>'.$item['name'] . '';
|
||||
if ($item['amount']>1) echo '(' . $item['amount'] . '*)';
|
||||
echo ' ' . $item['total'] . ',-</li>';
|
||||
}
|
||||
|
||||
echo '</ul></details>';
|
||||
} ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table>
|
||||
|
||||
<?=render('_pagination', ['page'=>$page, 'pages'=>$pages]); ?>
|
||||
<?php } else {
|
||||
echo '<p>(nenalezeny žádné položky)</p><br>';
|
||||
} ?>
|
||||
|
||||
<?=render('_footer');?>
|
|
@ -1,52 +0,0 @@
|
|||
<?=render('_header', ['title'=>'Členové']);?>
|
||||
|
||||
<form method="get">
|
||||
<div class="field has-addons">
|
||||
<div class="control is-expanded">
|
||||
<input name="searchFor" class="input" type="search" placeholder="část jména, emailové adresy nebo telefonu" value="<?=$searchFor; ?>">
|
||||
</div>
|
||||
<div class="control">
|
||||
<input type="submit" class="button is-info" value="Najít">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<br>
|
||||
|
||||
<h1>Členové</small></h1>
|
||||
|
||||
<?php if (count($members)) { ?>
|
||||
|
||||
|
||||
|
||||
<table class="table">
|
||||
<tr><th>jméno</th><th>pozn.</th><th></th><th></th></tr>
|
||||
<?php foreach ($members as $member) { ?>
|
||||
<tr>
|
||||
<td><?=$member['name']; ?><?php if (!$member['is_active']) { ?> <span class="tag is-warning">neaktivní</span><?php } ?></td>
|
||||
<td><?=$member['note']; ?></td>
|
||||
<td><a href="/clenove/detail/<?=$member['id']; ?>/" class=""><span class="icon"><i class="fas fa-search"></i></span></a> </td>
|
||||
<td><a href="/clenove/upravit/<?=$member['id']; ?>/" class=""><span class="icon"><i class="fas fa-edit"></i></span></a> </td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table>
|
||||
|
||||
<?=render('_pagination', ['page'=>$page, 'pages'=>$pages]); ?>
|
||||
<?php } else {
|
||||
echo '<p>(nenalezeny žádné položky)</p><br>';
|
||||
} ?>
|
||||
|
||||
<a href="/clenove/pridat/" class="button is-primary">Přidat člena</a>
|
||||
|
||||
<br><br>
|
||||
<form method="post">
|
||||
<div class="field has-addons">
|
||||
<div class="control is-expanded">
|
||||
<input name="qrcode" class="input" type="search" placeholder="QR kód kartičky" id="qrcode">
|
||||
</div>
|
||||
<div class="control">
|
||||
<input type="submit" class="button is-info" value="QR!">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?=render('_footer');?>
|
|
@ -1,5 +0,0 @@
|
|||
<?= render('_header'); ?>
|
||||
|
||||
<a href="/pokladna/dobit/" class="button is-big is-primary">dobít kredit</a>
|
||||
|
||||
<?= render('_footer'); ?>
|
|
@ -1,29 +0,0 @@
|
|||
<?=render('_header', ['title'=>'Sklad']);?>
|
||||
|
||||
<h1>Sklad</small></h1>
|
||||
|
||||
<?php if (count($items)) { ?>
|
||||
<table class="table">
|
||||
<tr><th>název</th><th>cena</th><th>pozn.</th><th>počet na skladě</th><th></th></tr>
|
||||
<?php foreach ($items as $item) { ?>
|
||||
<tr>
|
||||
<td><?=$item['name']; ?></td>
|
||||
<td><?=$item['price']; ?>,-</td>
|
||||
<td><?=$item['note']; ?></td>
|
||||
<td class="has-text-right">
|
||||
<?php
|
||||
$class = '';
|
||||
if ($item['amount']>0 && $item['amount']<5) $class = 'has-background-danger';
|
||||
if ($item['amount']>4 && $item['amount']<10) $class = 'has-background-warning';
|
||||
?>
|
||||
<span class="<?=$class; ?>"><?=$item['amount']; ?></span>
|
||||
</td>
|
||||
<td><a href="/sklad/pocet/<?=$item['id']; ?>/" class=""><span class="icon"><i class="fas fa-edit"></i></span></a> </td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</table>
|
||||
<?php } else {
|
||||
echo '<p>(nenalezeny žádné položky)</p><br>';
|
||||
} ?>
|
||||
|
||||
<?=render('_footer');?>
|
Loading…
Reference in New Issue