Timecard v1.0.0
This commit is contained in:
parent
4b429c2429
commit
a86fe2a85b
@ -8,5 +8,7 @@ return [
|
||||
"password" => ""
|
||||
],
|
||||
|
||||
"admin-password" => "admin",
|
||||
"canonical" => "http://localhost/timecard/",
|
||||
"heads" => [],
|
||||
];
|
||||
|
7
css/bootstrap.min.css
vendored
Normal file
7
css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,4 +1,8 @@
|
||||
<?php
|
||||
|
||||
ini_set("display_erros", "on");
|
||||
require_once __DIR__ . '/provide/autoload.php';
|
||||
|
||||
$boot = new BootLoader(__DIR__);
|
||||
$boot->run();
|
||||
|
||||
|
@ -8,16 +8,3 @@
|
||||
require_once __DIR__ . '/ClassLoader.php';
|
||||
spl_autoload_register(array("ClassLoaderXProvide", "loadClass"));
|
||||
|
||||
$config = require_once __DIR__ . '/../config.php';
|
||||
$db = new IDB();
|
||||
if (!$db->Connect($config["mysql"]["hostname"],
|
||||
$config["mysql"]["dbname"],
|
||||
$config["mysql"]["username"],
|
||||
$config["mysql"]["password"])
|
||||
)
|
||||
{
|
||||
echo 'can not connect to mysql server.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = $db->getDB();
|
||||
|
162
provide/classes/BootLoader.php
Normal file
162
provide/classes/BootLoader.php
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/***
|
||||
* Copyright (c) 2022 DevRas
|
||||
*
|
||||
*/
|
||||
|
||||
class BootLoader
|
||||
{
|
||||
public function __construct($root)
|
||||
{
|
||||
$this->root = $root;
|
||||
$this->session = new UserSession();
|
||||
|
||||
$this->model = new Template($this->root . "/template");
|
||||
}
|
||||
|
||||
protected $root;
|
||||
protected $pdo;
|
||||
protected $cards;
|
||||
protected $config;
|
||||
protected $session;
|
||||
protected $model;
|
||||
|
||||
public function run()
|
||||
{
|
||||
try {
|
||||
$this->InitPDO();
|
||||
$this->cards = new Timecard($this->pdo);
|
||||
$this->cards->InitTables();
|
||||
$user = new User($this->pdo);
|
||||
|
||||
$isAdmin = false;
|
||||
$loginUser = [];
|
||||
$works = [];
|
||||
|
||||
$page = filter_input(INPUT_GET, "p") ?? "home";
|
||||
|
||||
if ($user->hasLogout())
|
||||
{
|
||||
$this->session->setUsername(null);
|
||||
header("Location: ?login");
|
||||
exit;
|
||||
}
|
||||
|
||||
$logged = $this->session->isLogged();
|
||||
if (!$logged)
|
||||
{
|
||||
$loginUser = $user->hasLogin();
|
||||
if ($loginUser)
|
||||
{
|
||||
$this->session->setUsername($loginUser["username"]);
|
||||
$logged = true;
|
||||
} else
|
||||
{
|
||||
$this->model->viewModel("login", [
|
||||
"method" => "POST",
|
||||
"canonical" => $this->config["canonical"],
|
||||
"config" => $this->config
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$loginUser = $user->getUser($this->session->getUsername());
|
||||
if (!$loginUser)
|
||||
{
|
||||
throw new \RuntimeException("不正なユーザーです");
|
||||
}
|
||||
|
||||
$isAdmin = array_search($this->session->getUsername(), $this->config["admin_users"]) !== false;
|
||||
|
||||
if ($page == "passwd")
|
||||
{
|
||||
if ($user->hasUpdatePassword($loginUser))
|
||||
{
|
||||
header("Location: ?p=home");
|
||||
exit;
|
||||
}
|
||||
|
||||
$this->model->viewModel("passwd", [
|
||||
"username" => $this->session->getUsername(),
|
||||
"config" => $this->config,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($page == "create" && $isAdmin)
|
||||
{
|
||||
if ($user->hasCreate())
|
||||
{
|
||||
header("Location: ?p=home");
|
||||
exit;
|
||||
}
|
||||
|
||||
$this->model->viewModel("create", [
|
||||
"config" => $this->config,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($page == "view")
|
||||
{
|
||||
$id = filter_input(INPUT_GET, "id");
|
||||
$loginUser = $user->getUserById($id);
|
||||
if (!$loginUser)
|
||||
{
|
||||
throw new \RuntimeException("不正なユーザーです");
|
||||
}
|
||||
}
|
||||
|
||||
$result = $this->cards->hasCard($loginUser["id"], $isAdmin);
|
||||
$works = $this->cards->SelectTimes($loginUser["id"]);
|
||||
$lastCard = $this->cards->getLastInsert($loginUser["id"]);
|
||||
|
||||
$users = $this->cards->getUsers();
|
||||
$this->model->viewModel("view", [
|
||||
"logged" => $logged,
|
||||
"users" => $users,
|
||||
"user" => $loginUser,
|
||||
"works" => $works,
|
||||
"canonical" => $this->config["canonical"],
|
||||
"config" => $this->config,
|
||||
"addCard" => $result,
|
||||
"lastCard" => $lastCard,
|
||||
"isAdmin" => $isAdmin,
|
||||
]);
|
||||
} catch (\RuntimeException $e)
|
||||
{
|
||||
http_response_code(401);
|
||||
|
||||
$result = $this->model->viewModel("error", [
|
||||
"exception" => $e,
|
||||
"message" => $e->getMessage(),
|
||||
"config" => $this->config,
|
||||
]);
|
||||
|
||||
if (!$result)
|
||||
{
|
||||
echo $e->getMessage();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function InitPDO()
|
||||
{
|
||||
$config = require_once $this->root . '/config.php';
|
||||
|
||||
$db = new IDB();
|
||||
if (!$db->Connect($config["mysql"]["hostname"],
|
||||
$config["mysql"]["dbname"],
|
||||
$config["mysql"]["username"],
|
||||
$config["mysql"]["password"])
|
||||
)
|
||||
{
|
||||
throw new \RuntimeException('can not connect to mysql server.');
|
||||
}
|
||||
|
||||
$this->pdo = $db->getDB();
|
||||
$this->config = $config;
|
||||
}
|
||||
}
|
11
provide/classes/CardType.php
Normal file
11
provide/classes/CardType.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
/***
|
||||
* Copyright (c) 2022 DevRas
|
||||
*
|
||||
*/
|
||||
|
||||
class CardType
|
||||
{
|
||||
public const START = 1;
|
||||
public const END = 2;
|
||||
}
|
29
provide/classes/Template.php
Normal file
29
provide/classes/Template.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/***
|
||||
* Copyright (c) 2022 DevRas
|
||||
*
|
||||
*/
|
||||
|
||||
class Template
|
||||
{
|
||||
public function __construct($root)
|
||||
{
|
||||
$this->root = $root;
|
||||
}
|
||||
|
||||
protected $root;
|
||||
|
||||
public function viewModel($model, $args = [])
|
||||
{
|
||||
$args["__LOADER__"] = $this;
|
||||
|
||||
$path = $this->root . DIRECTORY_SEPARATOR . $model . ".php";
|
||||
if (!file_exists($path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return @include $path;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,8 @@
|
||||
<?php
|
||||
/***
|
||||
* Copyright (c) 2022 DevRas
|
||||
*
|
||||
*/
|
||||
|
||||
class Timecard
|
||||
{
|
||||
@ -9,7 +13,218 @@ class Timecard
|
||||
|
||||
protected $pdo;
|
||||
|
||||
public function InsertTime()
|
||||
public function InitTables()
|
||||
{
|
||||
try {
|
||||
$pdo = $this->pdo;
|
||||
|
||||
$pdo->query("CREATE TABLE IF NOT EXISTS users(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, password VARCHAR(64) NOT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP);");
|
||||
$pdo->query("CREATE TABLE IF NOT EXISTS cards(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, uid INT NOT NULL, startTime DATETIME, endTime DATETIME, validate INT NOT NULL DEFAULT 0);");
|
||||
} catch (\PDOException $e)
|
||||
{
|
||||
throw new \RuntimeException("データベースの初期化中にエラーが発生しました。");
|
||||
}
|
||||
}
|
||||
|
||||
public function getUsers()
|
||||
{
|
||||
try {
|
||||
$smt = $this->pdo->prepare("SELECT * FROM users");
|
||||
$smt->execute([
|
||||
]);
|
||||
|
||||
$buf = array();
|
||||
while ( $row = $smt->fetch() )
|
||||
{
|
||||
$buf[] = array(
|
||||
"id" => $row["id"],
|
||||
"username" => $row["username"],
|
||||
"created_at" => $row["created_at"],
|
||||
);
|
||||
}
|
||||
|
||||
return $buf;
|
||||
} catch (\PDOException $e)
|
||||
{
|
||||
throw new \RuntimeException("SQLエラーが発生しました。発生箇所:getUsers");
|
||||
}
|
||||
}
|
||||
|
||||
public function hasCard($id, $admin)
|
||||
{
|
||||
$uid = filter_input(INPUT_POST, "uid");
|
||||
$mode = filter_input(INPUT_POST, "reg");
|
||||
$date = filter_input(INPUT_POST, "date");
|
||||
|
||||
if (!$uid || !$mode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($uid < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$admin && $id != $uid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$admin)
|
||||
{
|
||||
$date = "";
|
||||
}
|
||||
|
||||
switch ($mode)
|
||||
{
|
||||
case "auto":
|
||||
$this->InsertTime($uid, $date);
|
||||
break;
|
||||
case "start":
|
||||
$this->InsertTimeManual(CardType::START, $uid, $date);
|
||||
break;
|
||||
case "end":
|
||||
$this->InsertTimeManual(CardType::END, $uid, $date);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function SelectTimes($uid)
|
||||
{
|
||||
try {
|
||||
$today = ((int) date("d")) - 1;
|
||||
$dayCount = (int) date("t");
|
||||
|
||||
$startTime = date("Y-m-d 00:00:00", strtotime(sprintf("-%ddays", $today)));
|
||||
$endTime = date("Y-m-d 00:00:00", strtotime(sprintf("+%ddays", $dayCount - $today)));
|
||||
|
||||
$smt = $this->pdo->prepare("SELECT * FROM cards WHERE startTime > ? AND endTime < ? AND uid=?;");
|
||||
$smt->execute([
|
||||
$startTime,
|
||||
$endTime,
|
||||
$uid
|
||||
]);
|
||||
|
||||
$buf = array();
|
||||
|
||||
while ($row = $smt->fetch())
|
||||
{
|
||||
$start = strtotime($row["startTime"]);
|
||||
$end = strtotime($row["endTime"]);
|
||||
|
||||
$diff = $end - $start;
|
||||
$workTime = $diff / 60 / 60;
|
||||
$workHour = floor($workTime);
|
||||
$workMinutes = floor(($workTime - $workHour) * 60);
|
||||
|
||||
$buf[] = array(
|
||||
"startTime" => $row["startTime"],
|
||||
"endTime" => $row["endTime"],
|
||||
"validate" => $row["validate"],
|
||||
"id" => $row["id"],
|
||||
"workTime" => $workTime,
|
||||
"workHour" => $workHour,
|
||||
"workMinutes" => $workMinutes,
|
||||
);
|
||||
}
|
||||
|
||||
return $buf;
|
||||
} catch (\PDOException $e)
|
||||
{
|
||||
throw new \RuntimeException("SQLエラーが発生しました。発生箇所:selectTimes");
|
||||
}
|
||||
}
|
||||
|
||||
public function InsertTime($uid, $date)
|
||||
{
|
||||
try {
|
||||
$smt;
|
||||
|
||||
$lix = $this->getLastInsert($uid);
|
||||
$now = date("Y-m-d H:i:s");
|
||||
if (strtotime($date))
|
||||
{
|
||||
$now = date("Y-m-d H:i:s", strtotime($date));
|
||||
}
|
||||
|
||||
if ( !$lix )
|
||||
{
|
||||
$smt = $this->pdo->prepare("INSERT INTO cards(uid, startTime) VALUES(?, ?);");
|
||||
$smt->execute([
|
||||
$uid,
|
||||
$now
|
||||
]);
|
||||
} else if ( $lix )
|
||||
{
|
||||
$smt = $this->pdo->prepare("UPDATE cards SET endTime = ?, validate = 1 WHERE id = ?;");
|
||||
$smt->execute([
|
||||
$now,
|
||||
$lix["id"]
|
||||
]);
|
||||
} else {
|
||||
throw new \RuntimeException("打刻できませんでした。原因:不明な操作");
|
||||
}
|
||||
|
||||
} catch (\PDOException $e)
|
||||
{
|
||||
throw new \RuntimeException("SQLエラーが発生しました。発生箇所:insertTime");
|
||||
}
|
||||
}
|
||||
|
||||
public function InsertTimeManual($type, $uid, $date)
|
||||
{
|
||||
try {
|
||||
$smt;
|
||||
|
||||
$lix = $this->getLastInsert($uid);
|
||||
$now = date("Y-m-d H:i:s");
|
||||
if (strtotime($date))
|
||||
{
|
||||
$now = date("Y-m-d H:i:s", strtotime($date));
|
||||
}
|
||||
|
||||
if ( !$lix && $type == CardType::START )
|
||||
{
|
||||
$smt = $this->pdo->prepare("INSERT INTO cards(uid, startTime) VALUES(?, ?);");
|
||||
$smt->execute([
|
||||
$uid,
|
||||
$now
|
||||
]);
|
||||
} else if ( $lix && $type == CardType::END )
|
||||
{
|
||||
$smt = $this->pdo->prepare("UPDATE cards SET endTime = ?, validate = 1 WHERE id = ?;");
|
||||
$smt->execute([
|
||||
$now,
|
||||
$lix["id"]
|
||||
]);
|
||||
} else {
|
||||
throw new \RuntimeException("打刻できませんでした。原因:始業が登録済みで始業をした。または、終業済みで終業をした。または、不明な操作。");
|
||||
}
|
||||
|
||||
} catch (\PDOException $e)
|
||||
{
|
||||
throw new \RuntimeException("SQLエラーが発生しました。発生箇所:insertTime");
|
||||
}
|
||||
}
|
||||
|
||||
public function getLastInsert($uid)
|
||||
{
|
||||
try {
|
||||
$smt = $this->pdo->prepare("SELECT * FROM cards WHERE uid = ? AND validate = 0 ORDER BY id DESC LIMIT 1;");
|
||||
|
||||
$smt->execute([
|
||||
$uid
|
||||
]);
|
||||
|
||||
return $smt->fetch();
|
||||
} catch (\PDOException $e)
|
||||
{
|
||||
throw new \RuntimeException("SQLエラーが発生しました。発生箇所:lastInsert");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
176
provide/classes/User.php
Normal file
176
provide/classes/User.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/***
|
||||
* Copyright (c) 2022 DevRas
|
||||
*
|
||||
*/
|
||||
|
||||
class User
|
||||
{
|
||||
public function __construct($pdo)
|
||||
{
|
||||
$this->pdo = $pdo;
|
||||
}
|
||||
|
||||
protected $pdo;
|
||||
|
||||
public function formalPassword($password)
|
||||
{
|
||||
return hash("sha256", $password);
|
||||
}
|
||||
|
||||
public function hasLogout()
|
||||
{
|
||||
$filter = filter_input(INPUT_GET, "logout");
|
||||
if ($filter)
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function hasLogin()
|
||||
{
|
||||
$username = filter_input(INPUT_POST, "username");
|
||||
$password = filter_input(INPUT_POST, "password");
|
||||
|
||||
if (!$username || !$password)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $this->Login($username, $password);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function hasUpdatePassword()
|
||||
{
|
||||
$username = filter_input(INPUT_POST, "username");
|
||||
$password = filter_input(INPUT_POST, "password");
|
||||
$newPassword = filter_input(INPUT_POST, "newPassword");
|
||||
|
||||
if (!$username || !$password || !$newPassword)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$currentUser = $this->Login($username, $password);
|
||||
if (!$currentUser)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $this->updatePassword($currentUser, $newPassword);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function hasCreate()
|
||||
{
|
||||
$username = filter_input(INPUT_POST, "username");
|
||||
$password = filter_input(INPUT_POST, "password");
|
||||
$mode = filter_input(INPUT_POST, "mode");
|
||||
|
||||
if (!$username || !$password || !$mode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $this->Create($username, $password);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function updatePassword($currentUser, $newPassword)
|
||||
{
|
||||
try {
|
||||
$formal = $this->formalPassword($newPassword);
|
||||
|
||||
$smt = $this->pdo->prepare("UPDATE users SET password=? WHERE id=?");
|
||||
$smt->execute([
|
||||
$formal,
|
||||
$currentUser["id"]
|
||||
]);
|
||||
|
||||
return true;
|
||||
} catch (\PDOException $e)
|
||||
{
|
||||
throw new \RuntimeException("SQLエラーが発生しました。パスワードの更新に失敗しました。");
|
||||
}
|
||||
}
|
||||
|
||||
public function Login($username, $password)
|
||||
{
|
||||
try {
|
||||
$formal = $this->formalPassword($password);
|
||||
|
||||
$smt = $this->pdo->prepare("SELECT * FROM users WHERE username=? AND password=?;");
|
||||
$smt->execute([
|
||||
$username,
|
||||
$formal
|
||||
]);
|
||||
|
||||
return $smt->fetch();
|
||||
} catch (\PDOException $e)
|
||||
{
|
||||
throw new \RuntimeException("SQLエラーが発生しました。発生箇所:UserLogin");
|
||||
}
|
||||
}
|
||||
|
||||
public function Create($username, $password)
|
||||
{
|
||||
$user = $this->getUser($username);
|
||||
if ($user)
|
||||
{
|
||||
throw new \RuntimeException("操作を続行できません。そのユーザー名は既に存在します。");
|
||||
}
|
||||
|
||||
try {
|
||||
$smt = $this->pdo->prepare("INSERT INTO users(username, password) VALUES(?, ?);");
|
||||
$formal = $this->formalPassword($password);
|
||||
|
||||
$smt->execute([
|
||||
$username,
|
||||
$formal
|
||||
]);
|
||||
|
||||
return true;
|
||||
} catch (\PDOException $e)
|
||||
{
|
||||
throw new \RuntimeException("SQLエラーが発生しました。発生箇所:createUser");
|
||||
}
|
||||
}
|
||||
|
||||
public function getUser($username)
|
||||
{
|
||||
try {
|
||||
$smt = $this->pdo->prepare("SELECT * FROM users WHERE username=?");
|
||||
|
||||
$smt->execute([
|
||||
$username
|
||||
]);
|
||||
|
||||
return $smt->fetch();
|
||||
} catch (\PDOException $e)
|
||||
{
|
||||
throw new \RuntimeException("SQLエラーが発生しました。発生箇所:getUser");
|
||||
}
|
||||
}
|
||||
|
||||
public function getUserById($id)
|
||||
{
|
||||
try {
|
||||
$smt = $this->pdo->prepare("SELECT * FROM users WHERE id=?");
|
||||
|
||||
$smt->execute([
|
||||
$id
|
||||
]);
|
||||
|
||||
return $smt->fetch();
|
||||
} catch (\PDOException $e)
|
||||
{
|
||||
throw new \RuntimeException("SQLエラーが発生しました。発生箇所:getUser");
|
||||
}
|
||||
}
|
||||
}
|
35
provide/classes/UserSession.php
Normal file
35
provide/classes/UserSession.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/***
|
||||
* Copyright (c) 2022 DevRas
|
||||
*
|
||||
*/
|
||||
|
||||
class UserSession
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
@session_start();
|
||||
}
|
||||
|
||||
public $SessionName = "devras_timecard";
|
||||
|
||||
public function isLogged()
|
||||
{
|
||||
if (!isset($_SESSION[$this->SessionName]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !empty($_SESSION[$this->SessionName]);
|
||||
}
|
||||
|
||||
public function getUsername()
|
||||
{
|
||||
return $_SESSION[$this->SessionName];
|
||||
}
|
||||
|
||||
public function setUsername($value)
|
||||
{
|
||||
$_SESSION[$this->SessionName] = $value;
|
||||
}
|
||||
}
|
78
template/create.php
Normal file
78
template/create.php
Normal file
@ -0,0 +1,78 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ja">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>ユーザー作成 | タイムカード</title>
|
||||
<link rel="canonical" href="<?php echo $args["canonical"]; ?>" />
|
||||
<link rel="stylesheet" href="<?php echo $args["canonical"]; ?>css/bootstrap.min.css" />
|
||||
<?php foreach ($args["config"]["heads"] as $key => $val): ?>
|
||||
<?php echo $val; ?>
|
||||
<?php endforeach; ?>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h2>タイムカード</h2>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<h3>ユーザー作成</h3>
|
||||
|
||||
<p>
|
||||
作成するユーザー名、パスワードを入力後作成ボタンを押してください。
|
||||
</p>
|
||||
|
||||
<form class="form" method="POST">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
<label for="username" class="form-label">ユーザー名</label>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input type="text" value="" class="form-control" name="username" id="username" />
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
ユーザー名を入力してください。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
<label for="password" class="form-label">パスワード</label>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input type="password" value="" class="form-control" name="password" id="password" />
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
パスワードを入力してください。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="mode" value="create" />
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<button class="btn btn-primary" type="submit">作成</button>
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<footer class="footer">
|
||||
<div class="container text-center">
|
||||
<p class="text-muted">
|
||||
Copyright © 2022 <a href="https://devras.net">DevRas</a> All Rights Reserved.
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
TimeCard v1.0.0
|
||||
<a href="https://github.com/kemasama/Timecard">github</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
49
template/error.php
Normal file
49
template/error.php
Normal file
@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ja">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>エラー | タイムカード</title>
|
||||
<link rel="canonical" href="<?php echo $args["config"]["canonical"]; ?>" />
|
||||
<link rel="stylesheet" href="<?php echo $args["config"]["canonical"]; ?>css/bootstrap.min.css" />
|
||||
<?php foreach ($args["config"]["heads"] as $key => $val): ?>
|
||||
<?php echo $val; ?>
|
||||
<?php endforeach; ?>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h2>タイムカード</h2>
|
||||
<p>
|
||||
<a href="?logout=1">ログアウト</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<h3>エラー</h3>
|
||||
<p>
|
||||
サービスの処理中にエラーが発生しました。<br />
|
||||
ホームに戻るには<a href="<?php echo $args["config"]["canonical"]; ?>">こちら</a>をクリックしてください。<br />
|
||||
</p>
|
||||
<code>
|
||||
<?php echo $args["message"]; ?>
|
||||
</code>
|
||||
<p>
|
||||
エラーが続けて発生する場合は、サーバー管理者にお問い合わせください。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<footer class="footer">
|
||||
<div class="container text-center">
|
||||
<p class="text-muted">
|
||||
Copyright © 2022 <a href="https://devras.net">DevRas</a> All Rights Reserved.
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
TimeCard v1.0.0
|
||||
<a href="https://github.com/kemasama/Timecard">github</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
76
template/login.php
Normal file
76
template/login.php
Normal file
@ -0,0 +1,76 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ja">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>ログイン | タイムカード</title>
|
||||
<link rel="canonical" href="<?php echo $args["canonical"]; ?>" />
|
||||
<link rel="stylesheet" href="<?php echo $args["canonical"]; ?>css/bootstrap.min.css" />
|
||||
<?php foreach ($args["config"]["heads"] as $key => $val): ?>
|
||||
<?php echo $val; ?>
|
||||
<?php endforeach; ?>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h2>タイムカード</h2>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<h3>ログイン</h3>
|
||||
|
||||
<p>
|
||||
ログインするユーザー名、パスワードを入力後ログインボタンを押してください。
|
||||
</p>
|
||||
|
||||
<form class="form" method="POST">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
<label for="username" class="form-label">ユーザー名</label>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input type="text" value="" class="form-control" name="username" id="username" />
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
ユーザー名を入力してください。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
<label for="password" class="form-label">パスワード</label>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input type="password" value="" class="form-control" name="password" id="password" />
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
パスワードを入力してください。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<button class="btn btn-primary" type="submit">ログイン</button>
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<footer class="footer">
|
||||
<div class="container text-center">
|
||||
<p class="text-muted">
|
||||
Copyright © 2022 <a href="https://devras.net">DevRas</a> All Rights Reserved.
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
TimeCard v1.0.0
|
||||
<a href="https://github.com/kemasama/Timecard">github</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
89
template/passwd.php
Normal file
89
template/passwd.php
Normal file
@ -0,0 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ja">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>パスワード変更 | タイムカード</title>
|
||||
<link rel="canonical" href="<?php echo $args["canonical"]; ?>" />
|
||||
<link rel="stylesheet" href="<?php echo $args["canonical"]; ?>css/bootstrap.min.css" />
|
||||
<?php foreach ($args["config"]["heads"] as $key => $val): ?>
|
||||
<?php echo $val; ?>
|
||||
<?php endforeach; ?>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h2>タイムカード</h2>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<h3>パスワード変更</h3>
|
||||
|
||||
<p>
|
||||
ユーザー名と現在のパスワード、新しいパスワードを入力して変更ボタンをクリックしてください。
|
||||
</p>
|
||||
|
||||
<form class="form" method="POST">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
<label for="username" class="form-label">ユーザー名</label>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input type="text" value="<?php echo $args["username"]; ?>" class="form-control" name="username" id="username" />
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
ユーザー名を入力してください。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
<label for="password" class="form-label">現在パスワード</label>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input type="password" value="" class="form-control" name="password" id="password" />
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
現在のパスワードを入力してください。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
<label for="newpassword" class="form-label">新しいパスワード</label>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input type="password" value="" class="form-control" name="newPassword" id="newpassword" />
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
新しいパスワードを入力してください。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<button class="btn btn-primary" type="submit">変更</button>
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<footer class="footer">
|
||||
<div class="container text-center">
|
||||
<p class="text-muted">
|
||||
Copyright © 2022 <a href="https://devras.net">DevRas</a> All Rights Reserved.
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
TimeCard v1.0.0
|
||||
<a href="https://github.com/kemasama/Timecard">github</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
178
template/view.php
Normal file
178
template/view.php
Normal file
@ -0,0 +1,178 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ja">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>タイムカード</title>
|
||||
<link rel="canonical" href="<?php echo $args["canonical"]; ?>" />
|
||||
<link rel="stylesheet" href="<?php echo $args["canonical"]; ?>css/bootstrap.min.css" />
|
||||
<?php foreach ($args["config"]["heads"] as $key => $val): ?>
|
||||
<?php echo $val; ?>
|
||||
<?php endforeach; ?>
|
||||
<!-- Version 1.0.0 -->
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h2>タイムカード</h2>
|
||||
<p>
|
||||
<a href="?logout=1">ログアウト</a>
|
||||
<?php if($args["isAdmin"]): ?>
|
||||
<a href="?p=create">ユーザー作成</a>
|
||||
<?php endif; ?>
|
||||
<a href="?p=passwd">パスワード変更</a>
|
||||
</p>
|
||||
<p class="text-info">
|
||||
ようこそ、
|
||||
<?php echo $args["user"]["username"]; ?>
|
||||
さん!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="container mt-3">
|
||||
<?php if($args["addCard"]): ?>
|
||||
<p class="text-danger">タイムカードを登録しました。</p>
|
||||
<?php endif; ?>
|
||||
<form class="form" method="POST">
|
||||
<?php if($args["isAdmin"]): ?>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
<label for="username" class="form-label">ユーザー名</label>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<select name="uid" id="username" class="form-select">
|
||||
<option value="-1" disabled>◆ 選択してください ◆</option>
|
||||
<?php foreach($args["users"] as $user): ?>
|
||||
<?php if($user["id"] == $args["user"]["id"]): ?>
|
||||
<option value="<?php echo $user["id"]; ?>" selected><?php echo $user["username"]; ?></option>
|
||||
<?php else: ?>
|
||||
<option value="<?php echo $user["id"]; ?>"><?php echo $user["username"]; ?></option>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
タイムカードを登録したいユーザーを選択してください
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<input type="hidden" name="uid" value="<?php echo $args["user"]["id"]; ?>" />
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
打刻時刻
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<?php if($args["isAdmin"]): ?>
|
||||
<input class="form-control" type="datetime" name="date" value="<?php echo date("Y-m-d H:i:s"); ?>" />
|
||||
<?php else: ?>
|
||||
<input class="form-control" type="datetime" name="date" value="<?php echo date("Y-m-d H:i:s"); ?>" readonly />
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
打刻する時間になります。通常はそのままで問題ありません。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-2">
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<button class="btn btn-primary" type="submit" name="reg" value="start">始業</button>
|
||||
<button class="btn btn-primary" type="submit" name="reg" value="end">終業</button>
|
||||
<button class="btn btn-primary" type="submit" name="reg" value="auto">登録</button>
|
||||
</div>
|
||||
<div class="col-md-3 form-text">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php if($args["isAdmin"]): ?>
|
||||
<div class="container mt-3">
|
||||
<form class="form" method="GET">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-6">
|
||||
<select name="id" id="username" class="form-select">
|
||||
<?php foreach($args["users"] as $user): ?>
|
||||
<?php if($user["id"] == $args["user"]["id"]): ?>
|
||||
<option value="<?php echo $user["id"]; ?>" selected><?php echo $user["username"]; ?></option>
|
||||
<?php else: ?>
|
||||
<option value="<?php echo $user["id"]; ?>"><?php echo $user["username"]; ?></option>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<button class="btn btn-success" type="submit">移動</button>
|
||||
</div>
|
||||
<div class="col-md-3 text-muted">
|
||||
選択したユーザーのタイムカードを開きます。
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="p" value="view" />
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<hr />
|
||||
|
||||
<?php if($args["logged"]): ?>
|
||||
<div class="container mt-3">
|
||||
<?php if(empty($args["works"]) && !$args["lastCard"]): ?>
|
||||
<p class="text-danger">タイムカードは登録されていません。</p>
|
||||
<?php else: ?>
|
||||
<?php $hours = 0; $minutes = 0; ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-bordered">
|
||||
<tr>
|
||||
<th>始業</th>
|
||||
<th>終業</th>
|
||||
<th>実働時間</th>
|
||||
</tr>
|
||||
<?php if($args["lastCard"] && $args["lastCard"]["endTime"] == NULL): ?>
|
||||
<tr class="timecard">
|
||||
<td><?php echo $args["lastCard"]["startTime"]; ?></td>
|
||||
<td> - </td>
|
||||
<td> - </td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<?php foreach ($args["works"] as $k => $v): ?>
|
||||
<tr>
|
||||
<td><?php echo $v["startTime"]; ?></td>
|
||||
<td><?php echo $v["endTime"]; ?></td>
|
||||
<td><?php echo $v["workHour"]; ?>h <?php echo $v["workMinutes"]; ?>m</td>
|
||||
</tr>
|
||||
<?php $hours += $v["workHour"]; ?>
|
||||
<?php $minutes += $v["workMinutes"]; ?>
|
||||
<?php if ($minutes >= 60) {
|
||||
$hours += 1;
|
||||
$minutes -= 60;
|
||||
} ?>
|
||||
<?php endforeach; ?>
|
||||
<tr class="mt-1">
|
||||
<th>合計</th>
|
||||
<td><?php echo $hours; ?>h</td>
|
||||
<td><?php echo $minutes; ?>m</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="container">
|
||||
<footer class="footer">
|
||||
<div class="container text-center">
|
||||
<p class="text-muted">
|
||||
Copyright © 2022 <a href="https://devras.net">DevRas</a> All Rights Reserved.
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
TimeCard v1.0.0
|
||||
<a href="https://github.com/kemasama/Timecard">github</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user