Node.js(Express)×PostgressSQLを使ったチャットアプリ 2

## データベースからデータを取得する

``routes/index.js``を書き換えます。

```js
//　中略

router.get('/', async (req, res, next) => {
  try {
    const getQuery = 'SELECT *, TO_CHAR(created_at, \'YYYY年MM月DD日 HH24時MI分SS秒\') AS created_at FROM channel';
    const queryResult = await pool.query(getQuery)

    console.log(queryResult.rows)

  } catch (error) {
    console.error(error);
    // エラーハンドリング: サーバーエラーが発生した場合は500をクライアントに返す
    res.status(500).send('サーバーエラー');
  }
});

//　中略
```
``http://localhost:3000/``にアクセスしてターミナルにデータが表示されていればOKです

``routes/index.js``を書き換えます。

```js
router.get('/', async (req, res, next) => {
  try {
    const getQuery = 'SELECT *, TO_CHAR(created_at, \'YYYY年MM月DD日 HH24時MI分SS秒\') AS created_at FROM channel';
    const queryResult = await pool.query(getQuery)

    res.render('index', {
      title: 'Express',
      channelList: queryResult.rows
    })

  } catch (error) {
    console.error(error);
    // エラーハンドリング: サーバーエラーが発生した場合は500をクライアントに返す
    res.status(500).send('サーバーエラー');
  }
});
```

 ## 取得したデータを表示させる

 ``views/index.ejs``を書き換えます。

 ```html
<!DOCTYPE html>
<html lang="ja">

  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>

  <body>
    <div>
      <form action="/" method="post">
        <input type="text" name="title" placeholder="タイトル" required>
        <button type="submit">作成</button>
      </form>

      <ul class="main_list">
        <% channelList.forEach(function(channelItem) { %>
          <li class="main_list_item">
            <div class="list">
              <p class="title">
                <%= channelItem.channel_title %>
              </p>
              <p class="date">
                <%= channelItem.created_at %>
              </p>
            </div>
          </li>
        <% }); %>
      </ul>
    </div>

  </body>
</html>

 ```

``http://localhost:3000/``にアクセスしてデータベースに登録したデータが表示されていればOKです


## 新規ページを作成

新規でページを作成するためにapp.jsを書き換えます。

```js
const usersRouter = require('./routes/users');
const message = require('./routes/message'); //追加

const app = express();
//中略

app.use('/users', usersRouter);
app.use('/message', message); //追加

// catch 404 and forward to error handler
//中略
```

``routes/message.js``を``/message``というURLに紐づける処理をしています。

### ファイルを作成

1. ``routes``配下に``message.js``を作成
2. ``views``配下に``message.ejs``を作成

## トークページの作成

``routes/message.js``にコードを書きます。

```js

const express = require('express');
const router = express.Router();
const pool = require('../dbConnection');

router.get('/:channel_id', async (req, res, next) => {
  try {
    const channelId = req.params.channel_id;
    const getQuery = "SELECT * FROM channel WHERE channel_id = $1"

    const getQueryResult = await pool.query(getQuery, [channelId])

    res.render('message', {
      title: getQueryResult.rows[0].channel_title,
      channel: getQueryResult.rows[0],
    });
  } catch (error) {
    console.error(error);
    // エラーハンドリング: サーバーエラーが発生した場合は500をクライアントに返す
    res.status(500).send('サーバーエラー');
  }
});

module.exports = router;

```

``views/message.ejs``にコードを書きます。

```html
<!DOCTYPE html>
<html lang="ja">

  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>

  <body>
    <div class="wrapper">
      <p class="main-title">
        <%= title %>
      </p>
      <a href="/" class="btn">トップへもどる</a>
    </div>
  </body>

</html>
```
http://localhost:3000/message/1

![スクリーンショット 2023-12-20 5.21.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262417/a4f021c4-f15a-454c-1d64-f45a15044810.png)

このように表示されていればOKです

## トークページに投稿機能をつける

``views/message.ejs``にコードを追加します。

```html
<form action="/message/<%= channel.channel_id %>" method="post">
  <input type="text" name="message"required>
  <button>投稿</button>
</form>
```

``routes/message.js``にコードを追加します。

```js
// 中略
const dayjs = require('dayjs'); //　追加
const pool = require('../dbConnection');

// 中略

router.post('/:channel_id', async (req, res, next) => {
  try {
    const messages = req.body.message;
    const channelId = req.params.channel_id;
    const createdAt = dayjs().format('YYYY-MM-DD HH:mm');
    const insertQuery = "INSERT INTO messages (message, channel_id, created_at) VALUES ($1, $2, $3)";

    await pool.query(insertQuery, [messages, channelId, createdAt]);

    res.redirect('/message/' + channelId);

  } catch (error) {
    console.error(error);
    // エラーハンドリング: サーバーエラーが発生した場合は500をクライアントに返す
    res.status(500).send('サーバーエラー');
  }
});

module.exports = router;
```

フォームに値を入力してデータベースを確認してみてください。
``messages``のテーブルにデータが入っていればOKです。

### トークページに表示させる

``routes/message.js``を書き換えます。

```js
router.get('/:channel_id', async (req, res, next) => {
  try {
    const channelId = req.params.channel_id;
    const getChannelQuery = "SELECT * FROM channel WHERE channel_id = $1"
    //　↓追加
    const getMessagesQuery =
      "SELECT *, TO_CHAR(created_at, \'YYYY年MM月DD日 HH24時MI分SS秒\') AS created_at FROM messages WHERE channel_id = $1"

    const channelQueryResult = await pool.query(getChannelQuery, [channelId])
    const messagesQueryResult = await pool.query(getMessagesQuery, [channelId]) //　追加

    res.render('message', {
      title: channelQueryResult.rows[0].channel_title,
      channel: channelQueryResult.rows[0],
      messageList: messagesQueryResult.rows, //　追加
    });
  } catch (error) {
    console.error(error);
    // エラーハンドリング: サーバーエラーが発生した場合は500をクライアントに返す
    res.status(500).send('サーバーエラー');
  }
});

```

``views/message.ejs``にコードを追加

```html
// 中略
</form>

<% if (messageList.length) { %>
  <div>
      <ul class="main-list">
          <% messageList.forEach(function(messageItem) { %>
          <li class="main-list_item">
              <div class="list">
                  <p class="title"><%= messageItem.message %></p>
                  <p class="date"><%= messageItem.created_at %></p>
              </div>
          </li>
          <% }); %>
      </ul>
  </div>
<% } %>

// 中略
```

![スクリーンショット 2023-12-20 5.49.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262417/7a6edd8d-8682-5330-9693-b5092309122e.png)

上記のように表示されていればOKです

## トップページのチャンネルをリンクにする

``views/index.ejs``を書き換えます。

```html
// 中略
<li class="main_list_item">
  <a href="/message/<%= channelItem.channel_id %>" class="list">
    <p class="title">
      <%= channelItem.channel_title %>
    </p>
    <p class="date">
      <%= channelItem.created_at %>
    </p>
  </a>
</li>
// 中略
```
トップページからトークページに飛べるようになればOKです


## cssを書く

ここまで作成したものはデザインが全くできていないのでcssで装飾してください。

## updateとdeleteを使って機能を追加する

自走課題です、難しければDiscordで質問してください。