PleasanterのAPI使いやすくしたので、Next.jsから使ってみる。

# 前置き
去年のアドベントカレンダーで、以下にような投稿をしています。

[PleasanterのAPI関連メソッドを使いやすくしたい。](https://qiita.com/m-isik/items/84230cad966c4a0485aa)

PleasanterのAPIはそのままだと、なかなか使い勝手が悪い、だからクラスにまとめよう、というお話でした。

今回はその続き、実際に構築したクラスを利用し、Next.jsからAPIを使ってみようと思います。

# 環境
主な環境は以下のとおり
- next: 14.1.0
- react: 18
- tailwindcss: 3.3.0 

# 作るもののイメージ

#### Next.js
![screenshot-localhost_3000-2024.03.28-10_41_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/83fe9f73-729f-c30d-a675-9a1d2f86cbad.png)

単純にPleasanterのデータを画面に表示するだけです。

#### Pleasanter
APIで取得する先のleasanterのイメージ
![screenshot-localhost-2024.03.28-10_43_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/52d8353b-db9b-da50-5a81-73326808265b.png)

こっちもほぼプレーンの状態です。

# ソースコード

### Git
以下を参照してください。

https://github.com/m-ishikawa1980/next-pleasanter-sample

### 構成

Next.jsの構成は以下の通り

```
app
├components
│└PleasanerItem.tsx /Pleasaterの1レコード分を描画するコンポーネント
├lib
│└pleasanterClient.ts /API接続用
└page.tsx /メイン

```

### 環境変数

.envファイルを用意して、PleasanterのAPIキーとURLを設定します。

```.env
NEXT_PUBLIC_PLEASANTER_APY_KEY=XXXXXXXXXXXXXXXXXXXXXX
NEXT_PUBLIC_PLEASANTER_URL=http://XXXXXXX/
```

その上で、**npm run dev** で動くはず。

### ソース解説

#### pleasanterClient.ts
こちらは、[以前の記事](https://qiita.com/m-isik/items/84230cad966c4a0485aa)を参照してください。完全に外部から呼び出すので、Pleasanterのサーバスクリプト、スクリプトのメソッドなんかは、ザクっと削除しています。

#### page.tsx

```tsx
import {
    ApiColumnKeyDisplayType,
    ApiDataType,
    PleasanterApiClient,
    View,
} from "./lib/pleasanterClient";
import PleasanterItem from "./components/PleasanterItem";

const columns = ["IssueId", "Title", "Body", "Owner", "Status"];
const siteId = 11114883;

const getPleasanterRecords = async () => {
    try {
        let view = new View({});
        let gridColumnHash = columns;
        view.setGridColumnsByArray({ value: gridColumnHash });

        let filterStatus = ["200"];
        view.setColumnFilterHash({
            key: "Status",
            value: JSON.stringify(filterStatus),
        });

        view.ApiDataType = ApiDataType.KeyValues;
        view.ApiColumnKeyDisplayType = ApiColumnKeyDisplayType.ColumnName;
        view.ApiKey = process.env.NEXT_PUBLIC_PLEASANTER_APY_KEY;
        view.ApiVersion = 1.1;
        let res = await PleasanterApiClient.apiGet({
            id: siteId,
            view: view,
            url: process.env.NEXT_PUBLIC_PLEASANTER_URL!,
        });
        return res;
    } catch (err) {
        console.log(err);
    }
};

async function Home() {
    let res = await getPleasanterRecords();
    let rowItems: any[];
    rowItems = res.Response.Data;

    return (
        <>
            <div className=" py-8 px-8">
                <h1 className=" text-6xl">Home</h1>
                <div className=" flex">
                    {rowItems.map((rowItem) => (
                        <div key={rowItem.IssueId}>
                            <PleasanterItem
                                rowItem={rowItem}
                                columns={columns}
                            />
                        </div>
                    ))}
                </div>
            </div>
        </>
    );
}

export default Home;
```

##### 少し具体的に説明

```tsx
const columns = ["IssueId", "Title", "Body", "Owner", "Status"];
```
Pleasanterから取得したい項目を配列で指定します。後続のview生成時やcomponentで画面描画する時に利用します。

```tsx
const getPleasanterRecords = async () => {
    //～～省略～～
};
```
PleasnaterへのAPIリクエストViewを生成、pleasanterClientを呼び出します。Viewの使い方などは過去記事を参照ください。

```tsx
async function Home() {
    let res = await getPleasanterRecords();
    let rowItems: any[];
    rowItems = res.Response.Data;

    return (
        <>
            <div className=" py-8 px-8">
                <h1 className=" text-6xl">Home</h1>
                <div className=" flex">
                    {rowItems.map((rowItem) => (
                        <div key={rowItem.IssueId}>
                            <PleasanterItem
                                rowItem={rowItem}
                                columns={columns}
                            />
                        </div>
                    ))}
                </div>
            </div>
        </>
    );
}

export default Home;
```
pleasnaterClietnからのレスポンスを受け取り、mapで展開しつつPleasanterItemコンポーネントへ受け渡します。

#### PleasanterItem.tsx

```tsx
import React from "react";

type props = {
    rowItem: any;
    columns: string[];
};

const PleasanterItem = ({ rowItem, columns }: props) => {
    return (
        <>
            <div className="">
                <div className=" m-3 p-2 border w-auto">
                    {columns.map((column) => (
                        <p key={column} className=" text-3xl text-cyan-600">
                            {column} = {rowItem[column]}
                        </p>
                    ))}
                </div>
            </div>
        </>
    );
};

export default PleasanterItem;

```
難しいことはしておらず、受け取ったレコードデータ（rowItem）から、colmunsに設定されたPleasnater項目ごと展開し、画面描画しています。

# おわりに

最終的には、
```
npm i pleasanterClient
```
なんて、npmに登録できたらいいなぁ、などと思いつつ今回はここまでです。