Quantcast
Channel: CSSタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9004

プチ・スケジュール管理システム作ってみた

$
0
0

こんにちは、還暦女子です。

今度はスケジュール管理表を作ってみました。
お店や病院などの営業予定や出勤表、シフト表、マイスケジュール等CSSを工夫すれば色々使えるかなと思って考えました。
初めての試みがいっぱいで穴だらけのコードですが、とりあえず一通り動きました。

作りたい仕様

  • ログイン管理内で編集、別ページのプレビューで表示
  • HTMLで入力可
  • 祝日は自由にカスタマイズ
  • 毎月自動更新
  • データベースを使わないライトな作り

サイト設計とデザイン

plan.jpg

AdobeXDで作成しました。
サイトデザイン以外にも設定イメージ、マニュアル、プロトタイプでプレゼンテーションも使える便利マルチツールです。書き出しは画像形式以外にもプラグインを使えばPDFも可能です。

デザインを元にHTMLとCSSのテンプレートを作成します。
今回は水色ベース。

管理画面イメージ
write.jpg

プレビュー画面イメージ
prev.jpg

カレンダー管理画面

ログインすると当月の管理画面に移行します。
tableとname属性もphpのfor文で書き出し。
Postで変数に変換するのもfor文。プログラムって一つ一つ書かなくていいから便利です。
カレンダー部分はネットに載ってるものを拾ってきてカスタマイズしました。

更新するとfile_put_contents()でjsonファイルに上書きします。
ファイル名は変数を入れてdays'.$m.'.jsonとして常に当月のjsonを取得。
jsonは1月から12月の12個のファイルを作っておき、毎年このデータを使い回す予定です。
ログインとログアウトのページは省略します。

当月のカレンダー

control.php
<?php//当月のカレンダーsession_start();session_regenerate_id(true);if(isset($_SESSION['login'])===false){echo'ログインしていません。';exit();}//XSSfunctionhtml_esc($word){returnhtmlspecialchars($word,ENT_QUOTES,'UTF-8');}//トークン生成functiongetCSRFToken(){$nonce=base64_encode(openssl_random_pseudo_bytes(48));setcookie('XSRF-TOKEN',$nonce);return$nonce;}$token=getCSRFToken();$token=html_esc($token);date_default_timezone_set('Asia/Tokyo');//東京時間にする$y=date('Y');$m=date('m')+0;//+intをつけないと祝日設定できない$week=['日','月','火','水','木','金','土'];//月末の日を取得$lastday=date("t",mktime(0,0,0,$m,1,$y));//json更新require_once(dirname(__FILE__).'/timer.php');//ファイル名は月で変動$file=file_get_contents('./json/days'.$m.'.json');$data=mb_convert_encoding($file,'UTF8','ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');$array=json_decode($data,true);if($_SERVER['REQUEST_METHOD']==='POST'){//postトークン追加functionvalidateCSRFToken($post_token){returnisset($_COOKIE['XSRF-TOKEN'])&&$_COOKIE['XSRF-TOKEN']===$post_token;}if(isset($_POST['csrf_token'])&&validateCSRFToken($_POST['csrf_token'])){//OKだったら空文字でスルーecho'';}else{echo'トークンが不正です。';exit();}//パスをサーバーと合わせておくheader('Access-Control-Allow-Origin: ファイルパス');header('Access-Control-Allow-Methods: GET, POST, OPTIONS');header('X-Frame-Options: SAMEORIGIN');//postトークンここまで//name値をfor文で書き出しfor($i=0;$i<$lastday;$i++){$name[$i]=html_esc($_POST['name'.$i]);}//JSON形式に変換 $json=json_encode($name);//JSON書き出し//タイマー設定が作用するので前月にもデータを入れておかないと消えてしまうfile_put_contents('./json/days'.($m-1).'.json',$json);file_put_contents('./json/days'.$m.'.json',$json);//jsonファイルを取得、valueに再代入$file=file_get_contents('./json/days'.$m.'.json');//文字コードをUTF-8に変換する$data=mb_convert_encoding($file,'UTF8','ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');$array=json_decode($data,true);}?><!doctype html><htmllang="ja"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><title>スケジュールカレンダー管理画面 | 当月</title><metaname="viewport"content="width=device-width, initial-scale=1"><metaname="format-detection"content="telephone=no"><linkhref="https://fonts.googleapis.com/icon?family=Material+Icons"rel="stylesheet"><linkrel="stylesheet"href="common/reset.css"><linkrel="stylesheet"href="common/style.css"><!--ファビコン32x32--><linkrel="shortcut icon"href="favicon.ico"type="image/vnd.microsoft.icon"></head><body><divid="wrapper"><headerid="logout"class="clearfix"><ahref="logout.php">ログアウト</a></header><main><h1id="title">Myカレンダー管理画面</h1><divid="infoLeft"><div><pid="ym"><?phpecho$y;?><span><?phpecho$m;?></span></p><pid="next"><ahref="control2.php">翌月<spanclass="material-icons md-24">keyboard_arrow_right</span></a></p><pid="view"><atarget="_blank"rel="noopener"href="schedule.php">プレビュー</a></p></div><pid="info">HTMLも入力できます。<br>リンクや画像も貼ってカスタマイズができます。入力後更新ボタンを押すと表示用のページに自動入力されます。変更の場合は上書きしてください。</p></div><formaction=""method="post"><!-- トークンの値をvalueに --><inputtype="hidden"name="csrf_token"value="<?phpecho$token?>"><tableid="cale"><tr><?phpforeach($weekas$weeks){echo'<td>'.$weeks.'</td>';}?></tr><?php// 1日の曜日を取得$wd1=date("w",mktime(0,0,0,$m,1,$y));// その数だけ空白を表示for($i=1;$i<=$wd1;$i++){echo"<td> </td>";}// 1日から月末日までの表示$d=1;$n=0;//休日を共通にしたかったので別ファイルにrequire_once(dirname(__FILE__).'/holiday.php');//holiday.phpで祝日設定for($d=1;$d<=$lastday;$d++){echo'<td class="'.$holiday[$d].'"><span class="days">'.$d.'</span><textarea class="memo" name="name'.$n.'" value="'.$array[$n].'">'.$array[$n].'</textarea></td>';// 今日が土曜日の場合は…if(date("w",mktime(0,0,0,$m,$d,$y))==6){// 週を終了echo"</tr>";// 次の週がある場合は新たな行を準備if(checkdate($m,$d+1,$y)){echo"<tr>";}}$n++;}// 最後の週の土曜日まで移動$wdx=date("w",mktime(0,0,0,$m+1,0,$y));for($i=1;$i<7-$wdx;$i++){echo"<td> </td>";}?></table><pid="update"><inputtype="submit"value="更新する"></p></form></main><footer><small>Copyright 2020 All Rights Reserved. 無断転載禁止</small></footer></div></body></html>

翌月のカレンダー

最初の月設定
$m = date('m')+1になってます。

control2.php
<?php//翌月のカレンダーsession_start();session_regenerate_id(true);if(isset($_SESSION['login'])===false){echo'ログインしていません。';exit();}//XSSfunctionhtml_esc($word){returnhtmlspecialchars($word,ENT_QUOTES,'UTF-8');}//トークン生成functiongetCSRFToken(){$nonce=base64_encode(openssl_random_pseudo_bytes(48));setcookie('XSRF-TOKEN',$nonce);return$nonce;}$token=getCSRFToken();$token=html_esc($token);date_default_timezone_set('Asia/Tokyo');//東京時間にする$y=date('Y');$m=date('m')+1;//+intをつけないと祝日設定できない$week=['日','月','火','水','木','金','土'];//月末の日を取得$lastday=date("t",mktime(0,0,0,$m,1,$y));//jsonから翌月のデータ取得$file=file_get_contents('./json/days'.$m.'.json');$data=mb_convert_encoding($file,'UTF8','ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');$array=json_decode($data,true);//次月に日付分の空文字設定jsonへ書き出し//年末だけ特別if($m===12){$y=date('Y')+1;$days=[];for($i=0;$i<date("t",mktime(0,0,0,1,1,$y));$i++){$days[$i]='';}$file=json_encode($days);file_put_contents('./json/days1.json',$file);}else{$days=[];for($i=0;$i<date("t",mktime(0,0,0,($m+1),1,$y));$i++){$days[$i]='';}$file=json_encode($days);file_put_contents('./json/days'.($m+1).'.json',$file);}if($_SERVER['REQUEST_METHOD']==='POST'){//postトークン追加functionvalidateCSRFToken($post_token){returnisset($_COOKIE['XSRF-TOKEN'])&&$_COOKIE['XSRF-TOKEN']===$post_token;}if(isset($_POST['csrf_token'])&&validateCSRFToken($_POST['csrf_token'])){//OKだったら空文字でスルーecho'';}else{echo'トークンが不正です。';exit();}//パスをサーバーと合わせておくheader('Access-Control-Allow-Origin: ファイルパス');header('Access-Control-Allow-Methods: GET, POST, OPTIONS');header('X-Frame-Options: SAMEORIGIN');//postトークンここまで//name値をfor文で書き出しfor($i=0;$i<$lastday;$i++){$name[$i]=html_esc($_POST['name'.$i]);}//JSON形式に変換 $json=json_encode($name);//JSON書き出し、パーミッション変更忘れずにfile_put_contents('./json/days'.$m.'.json',$json);//jsonファイルを取得、valueに再代入$file=file_get_contents('./json/days'.$m.'.json');//文字コードをUTF-8に変換する$data=mb_convert_encoding($file,'UTF8','ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');$array=json_decode($data,true);}?><!doctype html><htmllang="ja"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><title>スケジュールカレンダー管理画面 | 翌月</title><metaname="viewport"content="width=device-width, initial-scale=1"><metaname="format-detection"content="telephone=no"><linkhref="https://fonts.googleapis.com/icon?family=Material+Icons"rel="stylesheet"><linkrel="stylesheet"href="common/reset.css"><linkrel="stylesheet"href="common/style.css"><!--ファビコン32x32--><linkrel="shortcut icon"href="favicon.ico"type="image/vnd.microsoft.icon"></head><body><divid="wrapper"><headerid="logout"class="clearfix"><ahref="logout.php">ログアウト</a></header><main><h1id="title">Myカレンダー管理画面</h1><divid="infoLeft"><div><pid="ym"><?phpecho$y;?><span><?phpecho$m;?></span></p><pid="next"><ahref="control.php">当月<spanclass="material-icons md-24">keyboard_arrow_right</span></a></p><pid="view"><atarget="_blank"rel="noopener"href="schedule2.php">プレビュー</a></p></div><pid="info">HTMLも入力できます。<br>リンクや画像も貼ってカスタマイズができます。入力後更新ボタンを押すと表示用のページに自動入力されます。変更の場合は上書きしてください。</p></div><formaction=""method="post"><!-- トークンの値をvalueに --><inputtype="hidden"name="csrf_token"value="<?phpecho$token?>"><tableid="cale"><tr><?phpforeach($weekas$weeks){echo'<td>'.$weeks.'</td>';}?></tr><?php// 1日の曜日を取得$wd1=date("w",mktime(0,0,0,$m,1,$y));// その数だけ空白を表示for($i=1;$i<=$wd1;$i++){echo"<td> </td>";}// 1日から月末日までの表示$d=1;$n=0;//休日を共通にしたかったので別ファイルにrequire_once(dirname(__FILE__).'/holiday.php');//holiday.phpで祝日設定for($d=1;$d<=$lastday;$d++){echo'<td class="'.$holiday[$d].'"><span class="days">'.$d.'</span><textarea class="memo" name="name'.$n.'" value="'.$array[$n].'">'.$array[$n].'</textarea></td>';// 今日が土曜日の場合は…if(date("w",mktime(0,0,0,$m,$d,$y))==6){// 週を終了echo"</tr>";// 次の週がある場合は新たな行を準備if(checkdate($m,$d+1,$y)){echo"<tr>";}}$n++;}// 最後の週の土曜日まで移動$wdx=date("w",mktime(0,0,0,$m+1,0,$y));for($i=1;$i<7-$wdx;$i++){echo"<td> </td>";}?></table><pid="update"><inputtype="submit"value="更新する"></p></form></main><footer><small>Copyright 2020 All Rights Reserved. 無断転載禁止</small></footer></div></body></html>

カレンダープレビュー画面

ここは管理画面と作りはほぼ一緒。file_get_contents()でjsonからデータを取得してます。
翌月の方は省略します。

schedule.php
<?phpdate_default_timezone_set('Asia/Tokyo');//東京時間にする$y=date('Y');$m=date('m')+0;$week=['日','月','火','水','木','金','土'];$lastday=date('t',mktime(0,0,0,$m,1,$y));//json取得$file=file_get_contents('./json/days'.$m.'.json');$data=mb_convert_encoding($file,'UTF8','ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');$array=json_decode($data,true);//デコードfunctiondecode_html($word){returnhtml_entity_decode($word);}?><!doctype html><htmllang="ja"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><title>スケジュールカレンダー | 当月</title><metaname="viewport"content="width=device-width, initial-scale=1"><metaname="format-detection"content="telephone=no"><linkhref="https://fonts.googleapis.com/icon?family=Material+Icons"rel="stylesheet"><linkrel="stylesheet"href="common/reset.css"><linkrel="stylesheet"href="common/style.css"><!--ファビコン32x32--><linkrel="shortcut icon"href="favicon.ico"type="image/vnd.microsoft.icon"></head><body><divid="wrapper"><headerid="frontHeader"><h1id="title">Myカレンダー予定表</h1><p>管理画面から書き出されたものが表示されています。</p></header><mainid="scheduleMain"><h2id="ym"><?phpecho$y;?><span><?phpecho$m;?></span></h2><pid="next"><ahref="schedule2.php">翌月<spanclass="material-icons md-24">keyboard_arrow_right</span></a></p><tableid="cale"><tr><?phpforeach($weekas$weeks){echo'<td>'.$weeks.'</td>';}?></tr><tr><?php// 1日の曜日を取得$wd1=date('w',mktime(0,0,0,$m,1,$y));// その数だけ空白を表示for($i=1;$i<=$wd1;$i++){echo"<td> </td>";}// 1日から月末日までの表示$d=1;$n=0;//当月用休日設定require_once(dirname(__FILE__).'/holiday.php');//holiday.phpで祝日$holiday設定for($d=1;$d<=$lastday;$d++){echo'<td class="'.$holiday[$d].'"><span class="days">'.$d.'</span><div class="memoUp">'.decode_html($array[$n]).'</div></td>';if(date("w",mktime(0,0,0,$m,$d,$y))==6){// 週を終了echo"</tr>";// 次の週がある場合は新たな行を準備if(checkdate($m,$d+1,$y)){echo"<tr>";}}$n++;}// 最後の週の土曜日まで空欄を作る$wdx=date("w",mktime(0,0,0,$m+1,0,$y));for($i=1;$i<7-$wdx;$i++){echo"<td> </td>";}?></tr></table></main><footer><small>Copyright 2020 All Rights Reserved. 無断転載禁止</small></footer></div></body></html>

祝日の共通設定ファイル

ここは各ファイルに共通インクルードとして一つにしました。書き換えを楽にする為に。
Google APIを使うのも有りですが、独自で休日を入れたかったりローカルで編集したいこともあり自作しました。
Classの付与をif文で条件分岐させてます。
毎年手書きで更新する必要がありますが。。。

※6月から作ったので6月から記述してます。

holiday.php
<?php//祝日の配列1$holiday=[];for($d;$d<=$lastday;$d++){$holiday[$d]='none';if($m===6){//月$holiday[$d]='none';}if($m===7){if($d===23||$d===24){$holiday[$d]='holiday';}else{$holiday[$d]='none';}}if($m===8){if($d===10){$holiday[$d]='holiday';}else{$holiday[$d]='none';}}if($m===9){if($d===21||$d===22){$holiday[$d]='holiday';}else{$holiday[$d]='none';}}if($m===10){$holiday[$d]='none';}if($m===11){if($d===3||$d===23){$holiday[$d]='holiday';}else{$holiday[$d]='none';}}if($m===12){if($d===23||$d===22){$holiday[$d]='holiday';}else{$holiday[$d]='none';}}}

自動更新タイマー設定

これが一番大変でした。
postしたデータはDBに格納することが多いと思いますが、DBを使うまでもないしお手軽に組み込みたい。
でも外部データを使わないとpostデータは失われてしまう。
そこでjsonを使うことにしました。
json使うの初めてです。

管理画面もプレビュー画面もここからfile_put_contents()とfile_get_contents()でデータを上書き、取得しています。
月が変わった時、先月のデータを取ってきて当月に上書きし翌月は日付分の空文字を挿入。
タイマーはif文でstrtotime(date('Y-m-d H:i:s'))より大か小かで振り分けてますが、これでいいのかイマイチ不安。
小刻みのタイマーテストはしてみましたが、ひと月たったらちゃんと動いているかどうか…

サーバ上で時をみながら確認して、変わってなかったら考えることにします。気長にゆるゆる開発。

timer.php
<?php//毎月1になったら自動でカレンダーを繰越し//当月になったら先月のデーターを移行するfunctiondaily($num){$file=file_get_contents('./json/days'.($num-1).'.json');$data=mb_convert_encoding($file,'UTF8','ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');$array=json_decode($data,true);$json=json_encode($array);file_put_contents('./json/days'.$num.'.json',$json);}//年初めの時functionstart_daily($num){$file=file_get_contents('./json/days12.json');$data=mb_convert_encoding($file,'UTF8','ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');$array=json_decode($data,true);$json=json_encode($array);file_put_contents('./json/days'.$num.'.json',$json);}if(strtotime(date('Y-01-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-02-01 00:00:00'))>strtotime(date('Y-m-d H:i:s'))){start_daily(1);}elseif(strtotime(date('Y-02-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-03-01 00:00:00'))>strtotime(date('Y-m-d H:i:s'))){daily(2);}elseif(strtotime(date('Y-03-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-04-01 00:00:00'))>strtotime(date('Y-m-d H:i:s'))){daily(3);}elseif(strtotime(date('Y-04-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-05-01 00:00:00'))>strtotime(date('Y-m-d H:i:s'))){daily(4);}elseif(strtotime(date('Y-05-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-06-01 00:00:00'))>strtotime(date('Y-m-d H:i:s'))){daily(5);}elseif(strtotime(date('Y-06-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-07-01 00:00:00'))>strtotime(date('Y-m-d H:i:s'))){daily(6);}elseif(strtotime(date('Y-07-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-08-01 00:00:00'))>strtotime(date('Y-m-d H:i:s'))){daily(7);}elseif(strtotime(date('Y-08-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-09-01 00:00:00'))>strtotime(date('Y-m-d H:i:s'))){daily(8);}elseif(strtotime(date('Y-09-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-10-01 00:00:00'))>strtotime(date('Y-m-d H:i:s'))){daily(9);}elseif(strtotime(date('Y-10-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-11-01 00:00:00'))>strtotime(date('Y-m-d H:i:s'))){daily(10);}elseif(strtotime(date('Y-11-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-12-01 00:00:00'))>strtotime(date('Y-m-d H:i:s'))){daily(11);}elseif(strtotime(date('Y-12-01 00:00:00'))<strtotime(date('Y-m-d H:i:s'))&&strtotime(date('Y-12-31 23:59:59'))>strtotime(date('Y-m-d H:i:s'))){daily(12);}else{//json初期値とりあえず作っておくfor($i=1;$i<13;$i++){file_put_contents('./days/days'.$i.'.json',null);}}

とりあえず作ってみて思ったこと

簡単なシステムでも、一つの形になるものを作るのってすごく難しいですね。
ほんの少し操作性がいいものを追加しようとすると2、3日は軽く悩む。
今までのコードは全て捨てて、新しく作り変えることも少なくないです。
まだまだ初心者なので知らないこともいっぱいあるし。

でも動いた時の感動は恐悦至極。これがあるからやめられない。
そろそろクラスやフレームワークも触ってみたいし、DBも挑戦してみようかななどと思っています。

就職が決まって6月下旬から働き始めたので、今までみたいにまとまった時間は作れなくなりました。
希望職のwebデザインですが仕事でプログラムを組むことは、まずなさそう。HTMLは触りますが。

でも開発はこれからも続けていくつもりです。


Viewing all articles
Browse latest Browse all 9004

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>