Node.jsでミニブログを作りました

こんにちはななしひろゆきです
この前はブラックジャックを作りましたが
今回はしっかり使えそうな物を作りました
ミニブログをつくりました

メイン画面です
![キャプチャ_main.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2879865/160dc1e6-7bb2-5b8a-b387-3b4c106e2292.png)

クリックすると
詳細画面に行けます
![キャプチャ_detail.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2879865/a6c3e3c6-f549-f4a2-007f-66eff1c0cae3.png)

次にjavascriptです
```app.js
'use strict'
const fs = require('fs');
var http = require('http')
const ejs = require('ejs');
const url = require('url');
var brog = require('./testsqlite3.js')
const express = require('express')
const bodyParser = require("body-parser");
  var data = [];
  var brog_detail = [];
  var select_title ;
  brog.brog_insert();
data =brog.brog();
var set_url ="index.ejs";
const html =fs.readFileSync('./ejs/'+set_url+'','utf-8')
var myCss = {
       style : fs.readFileSync('./test.css','utf8')
   };
/*   var myCss2 = {
          style : fs.readFileSync('.page/初登校.txt','utf8')
      };*/
const app= express()
app.use(express.json())
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
  var content;
app.get('/home',(request,response)=>{
   set_url ="index.ejs";
  if(!request.query.completed){
    content = ejs.render(fs.readFileSync('./ejs/'+set_url+'','utf-8'),{
             myCss: myCss,
             brogdata:data,
           });
    response.writeHead(200, {'Content-Type':'text/html'});
    response.write(content);
    response.end()
    return
  }
})
app.post('/brogdetail',(request,response)=>{
   set_url ="brogdetail.ejs";
   var title = request.body.title
   select_title = title;
  brog_detail = brog.search(title);
  var coment= brog.coment_search(title);

  coment.forEach((file=> {
  }));
  if(!request.query.completed){
    content = ejs.render(fs.readFileSync('./ejs/'+set_url+'','utf-8'),{
             myCss: myCss,
             brogdata:brog_detail,
             coment:coment,
           });
    response.writeHead(200, {'Content-Type':'text/html'});
    response.write(content);
    response.end()
    return
  }
})
app.post('/brogdetail_coment',(request,response)=>{
   set_url ="brogdetail.ejs";
   var title = select_title
  brog_detail = brog.search(title);
  var input_coment = request.body.title
  brog.coment_insert(input_coment,title);
  var coment= brog.coment_search(title);
  coment.forEach((file=> {
  }));
  if(!request.query.completed){
    content = ejs.render(fs.readFileSync('./ejs/'+set_url+'','utf-8'),{
             myCss: myCss,
             brogdata:brog_detail,
             coment:coment,
           });
    response.writeHead(200, {'Content-Type':'text/html'});
    response.write(content);
    response.end()
    return
  }
})
app.get('/AboutUs',(request,response)=>{
  set_url ="AboutUs.ejs";
  if(!request.query.completed){
    content = ejs.render(fs.readFileSync('./ejs/'+set_url+'','utf-8'),{
            title:"リチャ丸です",
            message:'',
             myCss: myCss,
             brogdata:data,
           });
    response.writeHead(200, {'Content-Type':'text/html'});
    response.write(content);
    response.end()
    return
  }
})
app.listen(3000)
```
次にtestsqlite3です
```testsqlite3.js
const Database = require('better-sqlite3');
const fs = require('fs');
const db = new Database('test_db.db', { verbose: console.log });
const stmt = db.prepare('SELECT * FROM brog ;');
const cats = stmt.all();
var box = [];
let detail = [];
var brog_detail = [];
var coment_detail = [];
module.exports.brog =()=>{
var test = db.prepare('SELECT * FROM brog WHERE brog_id = ? ORDER BY brog_id ASC;');
for(var i = 1; i<cats.length+1; i++){
var check = test.get(i);
   box.push([check.brog_id,check.name,check.detail,check.time])
}
  return box;
};
module.exports.search =(test) =>{
  detail[0] =  fs.readFileSync("./page/"+test+".txt", 'utf-8');
   stats = fs.statSync("./page/"+test+".txt");
    brog_detail = [test,detail[0],stats.mtime]
    return brog_detail;
};
module.exports.coment_search =(test) =>{
    const stmt2 = db.prepare(' SELECT coment_id,coment,coment_time FROM all_view WHERE brog_name = ?;');
    const set = stmt2.all(test);
  if (set.length === 0) {
  set[0] = {  coment_id: 0,  coment: 'コメントを残していただけると嬉しいです',  coment_time: ''}
}
  return set;
};
module.exports.coment_insert=(test, title) =>{
  // 年・月・日・曜日を取得
  const date = new Date();
const currentTime = formattedDateTime(date);
console.log(currentTime)


  console.log(test+'ここはインサート'+title)
  const select_title_id = db.prepare(' SELECT brog_id FROM brog WHERE name = ?;');
  const set_id =select_title_id.get(title)
  const insert_coment_detail = db.prepare('INSERT INTO coment_detail(coment,TIME)VALUES(?,?);');
insert_coment_detail.run(test,currentTime);
  const insert_coment = db.prepare('INSERT INTO coment(brog_id)VALUES(?);');
insert_coment.run(set_id.brog_id);
};

module.exports.brog_insert =() =>{
  const fileList = fs.readdirSync('./page')
  let title = [];
  var i = 0;
  var set = [];
  var set_detail = [];
  var data = [];
  var brog_detail = [];
  var stats
var count_brog = 0;
  fileList.forEach((file=> {
    count_brog++
  title[i] = file;
  set[i] =title[i].slice( 0, -4 ) ;
   detail[i] =  fs.readFileSync("./page/"+title[i], 'utf-8');
   set_detail[i] = detail[i].slice( 0,10 ) ;
   stats = fs.statSync("./page/"+title[i]);
   data.push([set[i],set_detail[i],stats.mtime])
  }))
if(cats.length === count_brog){

}else{
  for(var n = 0; n<count_brog; n++){
  const search_brog_input = db.prepare('SELECT * FROM brog WHERE name = ?;');
  const check = search_brog_input.all(data[n][0]);
  if(check.length === 0){
    var brog_name =''+data[n][0]+'' ;
    var brog_detail = ''+data[n][1]+'' ;
    var brog_time =  ''+data[n][2]+'' ;
      const insert_brog = db.prepare('INSERT INTO brog (name,detail,time)VALUES(?,?,?);');
    insert_brog.run(brog_name,brog_detail,brog_time);
  }
  }
}
};
function formattedDateTime(date) {
  const y = date.getFullYear();
  const m = ('0' + (date.getMonth() + 1)).slice(-2);
  const d = ('0' + date.getDate()).slice(-2);
  const h = ('0' + date.getHours()).slice(-2);
  const mi = ('0' + date.getMinutes()).slice(-2);
  const s = ('0' + date.getSeconds()).slice(-2);
var all =(y +'年'+ m +'月'+ d +'日'+ h +'時'+ mi +'分'+ s+'秒');
return all
}

```
次にejsです
```index.ejs
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>リチャ丸ブログ</title>
  <%- myCss.style %>
  </head>
  <body>
  <form method="post" action="/brogdetail" >
    <header class="header">
  <div class="container">
    <h1 class="logo">りちゃ丸のブログ</h1>
    <ul class="nav">
      <li><a href="/home">Home</a></li>
      <li><a href="/AboutUs">About Us</a></li>
    </ul>
  </div>
</header>
    <main>
      <% var i = 0; %>
      <% brogdata.forEach((file=> { %>
        <article>

         <%=  i%>
          <div class="test">
          <p style="text-align: right"><%= file[3]%></p>
          <h2><%=file[1] %></h2>
         <p><%=file[2] %>...</p>
         <div align="center" >
      <button  type="submit"class="btn btn-flat" name ="title" id ="title" value="<%= file[1] %>">全ての記事を読むならここをクリック</button>
       <% i ++ %>
       </div>
       </div>
        </article>
      <% }))%>
</main>
    <footer class="footer">
<div class="container">
    <ul class="nav">
        <li><a href="#fake">せんきゅーふぉあーうぉっちんぐ</a> </li>

    </ul>
</div>
  <p class="copy"> Copy rights @Vineeth.TR </p>
</footer>
</form>
  </body>
</html>
```
brogdetail.ejsです
```brogdetail.ejs
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>リチャ丸ブログ</title>
  <%- myCss.style %>
  </head>
  <body>
      <form method="post" action="/brogdetail_coment" >
    <header class="header">
  <div class="container">
    <h1 class="logo">りちゃ丸のブログ</h1>
    <ul class="nav">
      <li><a href="/home">Home</a></li>
      <li><a href="/AboutUs">About Us</a></li>
    </ul>
  </div>
</header>

<article>


  <div class="test">
  <p style="text-align: right"><%= brogdata[2]%></p>
  <h2 ><%= brogdata[0]%></h2>
 <p><%= brogdata[1]%></p>
 <div align="center" >
</div>
</div>
</article>
<div class="comentcover">
<div class="coment">
<h2>コメント一覧</h2>
</div>
<% coment.forEach((file=> { %>
  <div class ="coment_detail">
    <p> <%= file.coment %></p>
      <p style="text-align: right"><%= file.coment_time%></p>
</div>
  <%   })); %>
</div>
<div class="cp_iptxt">
	<input class="ef" type="text" placeholder=""  name="title" id="title">
	<label>コメント</label>
	<span class="focus_line"></span>
</div>
</form>
  </body>
  <footer class="footer">
<div class="container">
  <ul class="nav">
      <li><a href="#fake">せんきゅーふぉあーうぉっちんぐ</a> </li>

  </ul>
</div>
<p class="copy"> Copy rights @Vineeth.TR </p>
</footer>
<script>

    //var btn = document.getElementById('title');
var Myelement = document.getElementById("title");

   window.document.onkeydown = function(event){

        if (event.key === 'Enter') {
        }
    }
</script>
</html>
```
AboutUs.ejs
```AboutUs.ejs
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>リチャ丸ブログ</title>
  <%- myCss.style %>
  </head>
  <body>

    <header class="header">
  <div class="container">
    <h1 class="logo">りちゃ丸のブログ</h1>
    <ul class="nav">
      <li><a href="/home">Home</a></li>
      <li><a href="/AboutUs">About Us</a></li>
    </ul>
  </div>
</header>
    <main>
        <article>
          <div class="test">
          <h2>初めましてりちゃ丸です</h2>
         <p>りちゃ丸です。ミニブログでボルダリングが好きです</p>
       </div>
        </article>
</main>

    <footer class="footer">
<div class="container">
    <ul class="nav">
        <li><a href="#fake">せんきゅーふぉあーうぉっちんぐ</a> </li>

    </ul>
</div>
  <p class="copy"> Copy rights @Vineeth.TR </p>
</footer>
  </body>
</html>
```
続いてcssです
test.css
```test.css
<style>
.test {
  position: relative;
  padding: 1.5rem 1.5rem calc(1.5rem + 10px);
  border: 2px solid #000;

}
.test:time{

}
.test:after {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 10px;
  content: '';
  border-top: 2px solid #000;
  background-image: -webkit-repeating-linear-gradient(135deg, #000, #000 1px, transparent 2px, transparent 5px);
  background-image: repeating-linear-gradient(-45deg, #000, #000 1px, transparent 2px, transparent 5px);
  background-size: 7px 7px;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.blog {
    max-width: 1000px;
    margin-left: auto;
    margin-right: auto;
    padding-left: 16px;
    padding-right: 16px;
}
.footer{

  background:#0A95AA;
  color:#fff;
  height:100px
  position: absolute;/*←絶対位置*/
  bottom: 0; /*下に固定*/
}
.copy{
  font-size:10px;
  text-align:center
}
.container{
  max-width:1200px;
  padding:0 15px;
  width:100%;
}
.container:after {
    clear: both;
    content: "";
    display: table;
}
.header{
  height:60px;
  background:#00DAFC;
  color:#fff;
  width:100%;
}
.container{
  max-width:1200px;
  padding:0 15px;
  width:100%;
}
.logo{
  margin:0;
  line-height:50px;
  float:left;
}
.nav{
  list-style:none;
  float:left;
}
.nav li{display:inline-block;}
.nav li a{
  display:inline-block;
   padding:3px 15px;
  color:inherit;
  text-decoration:none;
}
.box {
  margin         : auto;                 /* サンプル用 中央寄せ */
  box-sizing     : border-box;           /* 罫線も含む長さ      */
  background     : #fff;                 /* BOXの背景色         */
/*  border         : 1px solid #666;       /* 枠線の指定          */
  width          : 1500px;                /* BOXの幅             */
  max-height     : 210px;                /* BOXの高さ           */
  animation: boxAnime 10s linear infinite alternate;

  /* ▼ inline-block時の定義 */
  letter-spacing : 0;                    /* 1行の高さを初期化   */
  line-height    : 1;                    /* 文字間隔を初期化    */
  text-align     : center;               /* 横位置定義          */
}

 /* --- サンプル確認用の親枠幅アニメーション ------------------ */
 /*     (BOXの並びには関係ありません)                           */
 /* --- 個別のBOXの定義 --------------------------------------- */
.box div {
  box-sizing     : border-box;           /* 罫線も含む長さ      */
  background     :#e4ab9b;          /* BOXの背景色         */
  /*  border         : 2px solid #35557f 枠線の指定          */
  width          : 700px;                 /* サンプルBOXの幅     */
  height         : 60px;                 /* サンプルBOXの幅     */
  margin         : 2px;                  /* サンプルBOXの間     */

  /* ▼ inline-blockの定義 */
  display        : inline-block;         /* インラインブロック化*/
}

body {
    max-width: 1500px;
    margin-left: auto;
    margin-right: auto;
    padding-left: 16px;
    padding-right: 16px;
}
table.tbl {
  border-collapse: collapse;
  text-align: left;
  line-height: 1.5;
}
table.tbl th {
  width: 150px;
  padding: 10px;
  font-weight: bold;
  vertical-align: top;
  border: 1px solid rgb(200,200,200);
}
table.tbl td {
  width: 350px;
  padding: 10px;
  vertical-align: top;
  border: 1px solid rgb(200,200,200);
}
.wrap{
  display:-ms-flexbox;
  display:-webkit-box;
  display:flex;
  justify-content:flex-start;
}
.wrap div{
  margin-right:5px;
}
/*button*/
*,
*:before,
*:after {
-webkit-box-sizing: inherit;
box-sizing: inherit;
}

html {
-webkit-box-sizing: border-box;
box-sizing: border-box;
font-size: 62.5%;
}

.btn,
button.btn {
    width:1000px;
font-size: 1.6rem;
font-weight: 700;
line-height: 1.5;
position: relative;
display: inline-block;
padding: 1rem 4rem;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-transition: all 0.3s;
transition: all 0.3s;
text-align: center;
vertical-align: middle;
text-decoration: none;
letter-spacing: 0.1em;
color:
#f7f9fa
;
border-radius: 0.5rem;
}

.btn-flat {
overflow: hidden;

padding: 1.5rem 6rem;

color: #fff;
border-radius: 0;
background: #010;
}

.btn-flat span {
position: relative;
}

.btn-flat:before {
position: absolute;
top: 0;
left: 0;

width: 30%;
height: 500%;

content: "";
-webkit-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;
-webkit-transform: translateX(-98%) translateY(-25%) rotate(45deg);
transform: translateX(-98%) translateY(-25%) rotate(45deg);

background: #00b7ee;
}

.btn-flat:hover:before {
-webkit-transform: translateX(-9%) translateY(-25%) rotate(45deg);
transform: translateX(-9%) translateY(-25%) rotate(45deg);
}
/*coment*/
.coment h2{
  padding: 1rem 2rem;
  border-left: 6px double #000;
}
.comentcover {
  padding: 1rem 2rem;
  border-top: 6px double #000;
  border-bottom: 6px double #000;
}
.coment_detail  {
 position: relative;
  margin-bottom: 2em;
  padding: 1.5rem 2rem;
  border-radius: 10px;
  background: #eee;
}

.coment_detail :before,
.coment_detail :after {
  position: absolute;
  content: '';
  border-radius: 50%;
  background: #eee;
}

.coment_detail :before {
  right: 30px;
  bottom: -15px;
  width: 30px;
  height: 30px;
}

.coment_detail :after {
  right: 50px;
  bottom: -30px;
  width: 15px;
  height: 15px;
}
/*textbox*/
.cp_iptxt {
	position: relative;
	width: 80%;
	margin: 40px 3%;
}
.cp_iptxt input[type='text'] {
	font: 15px/24px sans-serif;
	box-sizing: border-box;
	width: 100%;
	letter-spacing: 1px;
	padding-left: 4em;
}
.cp_iptxt input[type='text']:focus {
	outline: none;
}
.ef {
	padding: 4px 0;
	border: 0;
	border-bottom: 1px solid #1b2538;
	background-color: transparent;
}
.ef ~ .focus_line {
	position: absolute;
	bottom: 0;
	left: 0;
	width: 0;
	height: 2px;
	transition: 0.4s;
	background-color: #da3c41;
}
.ef:focus ~ .focus_line,
.cp_iptxt.ef ~ .focus_line {
	width: 100%;
	transition: 0.4s;
}
.ef ~ label {
	position: absolute;
	z-index: -1;
	top: 4px;
	left: 0;
	width: 100%;
	transition: 0.3s;
	letter-spacing: 0.5px;
	color: #aaaaaa;
}
.ef:focus ~ label, .cp_iptxt.ef ~ label {
	font-size: 12px;
	top: -16px;
	transition: 0.3s;
	color: #da3c41;
}
  </style>

```
データベース設計
```detabase.sql
CREATE TABLE brog(brog_id INTEGER PRIMARY KEY autoincrement,name VARCHAR(40),detail VARCHAR(40),time VARCHAR(40));
CREATE VIEW v_1 (brog_id,name,time,coment_id) AS
SELECT brog.brog_id,brog.name,brog.TIME,coment.coment_id FROM brog INNER JOIN coment ON brog.brog_id = coment.brog_id
/* v_1(brog_id,name,time,coment_id) */;
CREATE VIEW all_VIEW (brog_id,brog_name,brog_time,coment_id,coment,coment_time) AS
SELECT
v_1.brog_id,v_1.name,v_1.time,v_1.coment_id,coment_detail.coment,
 coment_detail.TIME
 FROM v_1
 INNER JOIN coment_detail ON
 v_1.coment_id = coment_detail.coment_id
/* all_VIEW(brog_id,brog_name,brog_time,coment_id,coment,coment_time) */;
CREATE TABLE sqlite_sequence(name,seq);
CREATE TABLE coment_detail(coment_id INTEGER PRIMARY KEY autoincrement,coment VARCHAR(100),TIME VARCHAR(30));
CREATE TABLE coment (coment_id INTEGER PRIMARY KEY autoincrement,brog_id INT);
```
感想
記事はtxtで作ってpageに入れて手打ちでbrogテーブルに入れる必要があります
インサートで入れる事も出来ますが今はこれでいいかなと思っています

今後としてはインサート文を回して入れれるようにしたり
snsサイトを作ったりしたいです
2か月前からNodeを触り始めてハンズオンＮｏｄｅ.ｊｓを見ながらやっていたのですが
ejsの使い方だとかベターsqlite3の使い方とかsqlite3を直接触る方法とかにはあまり触れてなかったので
全部自分で調べていれてました。もうＡＰＩリファレンスに抵抗感をあんまり感じなくなったような気がします
ただＡＷＳについてはまだ何も触れていません
今後の目標にしたいです

12月11日
pageにtxtの記事を作って入れるだけで動くようになりました
データベースも作り直しました