個人開発で1/3も思いが伝わらず心が折れかけた話

## はじめに
今回、妻のために作った個人開発が車輪の再発明で気落ちしたので供養として記事を投稿します。

〜数週間前〜
妻はiPhoneユーザーならお馴染みの『リマインダー』で買うものを管理していたのですが、商品のカテゴリー分けをしておらず画面を上下に行ったり来たりしていました。

その時、筆者は **<font color=red>「使いやすい『買うものリスト』アプリを作って喜んでもらおう！」</font>** と思いつき、早速行動に移しました。（この時ちゃんと「リマインダーが本当に使いづらいのか」を聞いておけば今回の顛末は避けられたのですが、妻に喜び＆褒めてもらえる未来しか筆者は空想していなかったのです）

〜約10日後〜
僕：「見て、これ作ってん！『シンプルな買うものリスト管理アプリ』！名付けて『KoreKau（コレカウ）』！」

妻：「ん？あんた『リマインダー』って知ってる？」

僕：「でも、〇〇（妻の名前）こないだ買い物の時に、リマインダーで上下行ったり来たりして使いづらそうやったやろ？」

妻：「<font color=lightgray>［筆者の個人開発を触りながら］</font> **私そんなん（リマインダー使いづらいなんて）言うたっけ？** そもそも、**あんたが考えるようなものでええの（良いアプリ）はもうあるで？絶対。** 
<font color=lightgray>［app store を開き］</font>ほら！これとか画像も載ってて、共有も簡単やし、おつかい機能とかむちゃええやん！ **これ一緒に使う？**」

僕：「<font color=lightgray>［もはやここらへんで心折れながら]</font>でも、せっかく作ったし…、ほら作ったこれも買うものの参照画像を載せれたり…」

妻：「参照画像とかそんなんいらん（必要ない）」

僕：「共有もできたり、ゴミ出し日のお知らせとか……」

妻：「いらんいらん、ゴミ出し日のお知らせとか別のスケジュールアプリで管理してるしなぁ。
そもそも、リマインダーが洗練されすぎてるねんて。（個人開発の）着眼点はええかもやけど、お知らせとか、スケジュールとか諸々のは **<font color=red>今使ってるので充分満足してるからもうええで（全く以て必要ない）</font>** 」

僕：（喜び＆褒めてもらおうと作ったのに…泣）


という感じで web制作に対するモチベーションが「もう疲れちゃって 全然動けなくてェ…」と旅コログのそれに近いものになりかけました。

そこで今回、冒頭にも書いたようにせめてもの供養としてここで紹介しようと思った次第です。
関心のある方はぜひ見て（そして使ってみて）ください。


## KoreKau | シンプルな買い物リスト管理アプリ

https://korekau.netlify.app/

![ogpImg-min.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/5f208796-f7cd-408e-ab62-8eb7b980f388.jpeg) 

- 技術スタック
    - react @18.2.0
    - typescript @5.3.3
    - vite @5.1.4
    - jotai @2.6.5
    - styled-components @6.1.8
    - swiper @11.0.7 
    - [Material Symbols](https://fonts.google.com/icons)（アイコンソース元）
    - Adobe llustrator 2024（ロゴ制作）   

![korekau01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/f6b122e3-82b1-2d1b-b37f-5efe2ce3ef05.gif)

※キャプチャ動画はPCで撮影したのでマウスカーソルが写っていますが、スマホやタブレットで使用する際は`swiper`によって上部のカテゴリーバーをタップまたは画面スワイプで遷移するようになっています。

## KoreKau（コレカウ）でできること

::: note info
これから説明していく、コレカウで扱う各種データ（買うものリストやカレンダー、ゴミ出し日の設定）の登録・管理はすべて`localStorage`で行っています。
:::

::: note alert
`localStorage`にはセキュリティリスクの可能性がありますので、個人情報やパスワードをはじめ、家族や他人のセンシティブ情報は絶対に登録しないでください。
:::

### 1.買うものを管理（追加・編集）
フォームから商品カテゴリーを選択して登録し、登録した買うものラベルを随時編集・削除できます。
登録内容は「カテゴリー、商品名、商品参照画像（任意）、メモ、個数、緊急度」です。

参照画像やメモがある場合は以下のようにアイコンが表示されて確認できるようになっています。

緊急度は「その商品がすぐに必要か」のシグナルで、登録時にトグルオンすると買うものラベルに背景色が付きます。

買うものラベルを編集してカテゴリーを変更すると自動で当該カテゴリーに組み分けられます。その際、緊急度オンにしていると優先的にリストの先頭近くに表示されます。

![korekau02.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/f610a4d4-04ee-6ad8-ea39-85d91c56bce7.gif)

また、登録した買うものリストを他の人と共有することも可能です。`json`形式で書き出されるファイルを読み込むことで自身のリストに反映されます。

![korekau03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/f912073d-8b1f-1c2e-b03b-84382a675305.gif)

### 2.商品価格の比較（どれがコスパの良い商品かチェック）
スーパーやドラッグストアなどで商品を買うときに **「どっちが本当にコスパが良いのか」と迷う** のが **【通常版】と【大容量のお得版】** じゃないでしょうか（筆者だけ？）。いつも「計算するの面倒だなぁ〜」と思っていたので、付加価値として追加した機能です。

例えば、洗剤を買おうとして【通常版：468g / 98円】と【大容量お得版：789g / 186円】では、どちらのほうが本当に【コスパ良し】かを把握できます。<font color=lightgray>（もはや計算するまでもないような比較例ですが）</font>

`［容量・個数］`に対象商品の単位を、`［価格］`に当該商品の価格を入力して`［計算］`を押すと結果が下部に表示されます。

![compareitems01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/ff52f1b0-de24-61b9-586a-6870c6da9c68.png)

### 3.カレンダー（簡易なスケジュール管理）

各日付にある`［+アイコン］`を押して表示される登録フォームから当該日のスケジュール（予定内容と開始・終了時間）を設定できます。買うものリストと同様にスケジュールの編集・削除も可能です。

![calendar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/cf27e875-0b97-3ca6-80b6-f6e8cf5183e9.png)

実は以下の記事で作ったものをそのまま移植できるのでは？と思い、追加した機能です。スタイルなどを微調整して追加しました。

https://qiita.com/benjuwan/items/12e85bb39e61498d2f10


### 4.ゴミ出し日（設定したゴミ出し日の前日を表示）
自治体や地域によっては家庭ごみを出せる曜日とゴミの種別が決まっているところもありますよね。
そこで【曜日】と【ゴミの種別】を設定することで、その前日になるとコレカウ画面上部に表示が出てきます。
<font color=lightgray>※記事執筆開始時は3/14日（木）でした。</font>

![trash001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/41b5f7ba-4ef8-2581-7185-0fb0fef9f9f7.png)

## 今回の個人開発を通して知ったこと
### `renderBullet`を使って`swiper`のページネーションに任意の文字列を指定できる

```js
import "swiper/css/pagination";
import { Pagination } from "swiper/modules";

const navListsLable = ['コレカウとは？', '買うものリスト', '商品価格の比較', 'カレンダー', 'ゴミ出し日'];
    const renderBullet = (index: number) => {
        return `<button type="button" class="swiper-pagination-bullet">${navListsLable[index]}</button>`;
    }

return (
    <SwiperLibsWrapper>
        <Swiper
            modules={[Pagination]}
            pagination={{ renderBullet, clickable: true }}
        >
        ..
        .
)
```

`JavaScript`でデフォルトのカルーセル用ビュレット（インジケーター？）を文字列に置き換えるしか無いと思っていたのですが、念の為ドキュメントを確認してみようと見ると`renderBullet`なるものがあるではないですか！

![スクリーンショット 2024-03-14 16.18.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/d5c89f7d-1224-e88d-d820-598d46bba5f5.png)

https://swiperjs.com/swiper-api#pagination

便利ですねー。`swiper`。

### `json`データの書き出し・読み込み
実装イメージについて雰囲気的には何となくはあったのですが具体的なコードを書くまでには至らず、流行り？の`claude 3`を使ってみることにしました。

https://claude.ai/chats

![スクリーンショット 2024-03-14 16.23.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/19d56948-bfa9-971a-7c95-cc604d8293c3.png)

一部調整しましたがほぼそのまま使えました。ありがとう`claude 3`！

ちなみに`claude 3`に聞く前に、同じ質問を`GPT-3.5`にもしてみましたが回答としては`localStorage`への保存方法（というか`localStorage`の使い方）という感じでした。

![スクリーンショット 2024-03-14 16.23.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/be0de532-b58e-0be4-9df5-783e9f0504aa.png)

筆者の雑いプロンプトから意図を汲み取って回答してくれた点で`claude 3`のほうが優秀でした。とはいえ`GPT-3.5`なので`GPT-4`だと変わってくるかもです。

あと、個人的な所感ですが`claude 3`のほうがUIとか洗練されていて良い印象を持ちました。

::: note info
この記事執筆中に、上司が`GPT-4`を使っていることを知り、上記の内容で試用させていただきました。

![スクリーンショット 2024-03-15 11.24.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/7ed6d901-be26-93f3-2f09-eec855044b2e.png)

結果としては`GPT-3.5`と似たような回答でした。しかし`GPT-3.5`では`JavaScript`の解説のみでしたが、`GPT-4`では`JavaScript`での実装例と`TypeScript`での実装例の両方を提示してくれていました。

とはいえ、同じプロンプト内容で意図を汲み取ってくれたのは結局`claude 3`という印象です。
:::

::: note warn
恥ずかしながらプロンプトにスペルミス（誤：`localstrrage`→正：`localStorage`）がありました。
ですので、上記の比較内容は正しい検証や検討にならない可能性があります。
@htsign さんにコメント欄で指摘いただきました。気づいていなかったので誠にありがとうございます。
:::


### オブジェクトの`sort`メソッド
今更ですが、`boolean`型や`string`型の`sort`の仕方を知りました。
いつものやり方<font color=lightgray>（今までは奇跡的にすべて`number`型だった）</font>でしようとすると`TypeScript`から怒られました。
こちらも生成AIに聞いて数秒で解決しました。
分かりやすい説明はもちろん、こちらがわざわざ言うまでもなくコードを例示してくれたりして、情報検索の方法が大きく変わったことを実感しています。
今回、`sort`メソッドについて改めて理解を深められたのは収穫でした。

![スクリーンショット 2024-03-14 17.05.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/16df75de-7660-5629-c07b-78314bc8372e.png)

![スクリーンショット 2024-03-14 17.06.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/a5258995-eb89-fb34-7333-a4b819f9e5be.png)

### `jotai`
使いやす過ぎて呼吸するようにインストールしていました。改めて状態管理のしやすさを体験できました。
本当ありがたい状態管理ライブラリです。

## さいごに
今回、供養として記事を書いてきましたが、改めて以下のような web制作に対するスタンスというか心構え？みたいなものを学べた気がします。

- ヒアリングほんと大事
- 一気に作ってからユーザーに見せるのではなく、ちょくちょく見せたり、確認したりして都度修正してブラッシュアップしていく（アジャイル開発？）
- 既存サービスからユーザーを剥がすには、今使っているものに対する優位性（大きな付加価値やメリット）が必要

しかし同時に、車輪の再発明と呼べるほどのクオリティでも無いよなぁとかも思いつつ、こうして記事に書いてみると「やっぱり web制作は奥深くて楽しいよなぁ〜、好きなんだなぁ〜」という気持ちを再認識できました。
懲りずに今後も色々と個人開発していきたいと思います！

ここまで読んでいただき、ありがとうございました。
コレカウの`GitHub`を置いておきますので、気になった方は自由にしてください。

https://github.com/Benjuwan/korekau

PS：妻にはいつも感謝しております！