Giter VIP home page Giter VIP logo

reohakase / simple-resas-app Goto Github PK

View Code? Open in Web Editor NEW
2.0 1.0 0.0 1.64 MB

RESAS(地域経済分析システム)に掲載されている各種人口データを、都道府県別にグラフで比較できます。

Home Page: https://resas.reoiam.dev

License: GNU General Public License v3.0

JavaScript 2.20% TypeScript 97.76% CSS 0.04%
nextjs pandacss storybook turborepo typescript playwright react-server-components vitest zod

simple-resas-app's Introduction

📊 RESAS 都道府県別 人口比較アプリ

desktop720p.mov

RESAS(地域経済分析システム)に掲載されている各種人口データを、都道府県別にグラフで比較できます。 株式会社ゆめみのフロントエンドコーディング試験の課題の一環で作成しました。

概要

  • 📦 React Server Component使用 RESAS APIに対するfetchとデータ整形は全てサーバー側で実行し、24時間のキャッシュ有効期限を与えています。
  • 🌙 ダークモード対応 FigmaのVariablesとCSS変数を使い、効率的にダークモード対応を行えるカラーパレットを用いました。
  • 📱 レスポンシブ対応 どのような画面サイズに対しても、読み込み過程でのCLSなく表示できます。
  • ♿ アクセシビリティ対応 Pagespeed Insightsでスコア100を記録しました。
  • 📤 Opengraph対応 URLを送るだけで、選択中の都道府県と統計の種類をわかりやすく共有できます。
  • 🤖 GitHub Actions使用 ESLint & Prettierの実行、Vitestのテストの実行、Storybookのインタラクションテストの実行、PlaywrightのE2Eテストの実行をPR毎に自動化しています。

Pagespeed Insights

モバイル デスクトップ
image image
https://pagespeed.web.dev/analysis/https-resas-reoiam-dev-all/w6wyqvlcfx?form_factor=mobile https://pagespeed.web.dev/analysis/https-resas-reoiam-dev-all/w6wyqvlcfx?form_factor=desktop

Opengraph

茨城県、千葉県、東京都の総人口 | RESAS 都道府県別 人口比較アプリケーション

X (Twitter) Slack Facebook LinkedIn
image image image image

Figma

https://www.figma.com/design/hsWBflpYMAqzRCIabKZYnJ/Yumemi?node-id=402-1692&t=v4Zz5MpKl4nAQQMe-1

技術スタック

  • Next.js14appルーター
  • Panda CSS 🐼 トークンとレシピを用いたデザインシステムの構築
  • Recharts 📊 グラフ描画
  • Zod 💎 スキーマとバリデータの定義
  • Storybook 📕 アクセシビリティやインタラクションテストの実行と見た目の確認
  • Vitest ⚡ ユニットテストの実行
  • Playwright 🎭 E2Eテストの実行
  • Turborepo ⚙️ モノレポのビルドやリントのキャッシュ管理

Note

定期試験と大学編入試験に起因する開発者の多忙により、ヘッダー内のテーマセレクタの実装にRadix UIへの依存が残ってしまっています。課題の要件に係る核心的機能ではないので、見逃してくださると幸いです。

環境構築の手順

依存関係のインストール

Node.jsとpnpmのバージョン管理にprototoolsを使用しています。まずは、以下のコマンドを実行するか、.prototoolsに記述されているバージョンのものを手動でインストールしてください。

proto use
pnpm i
pnpm lefthook install # コミット時チェックのGitフック管理ツールのインストール (初回のみ)
pnpm playwright install --with-deps # StorybookのインタラクションテストのCLI実行 & E2Eテストの実行に必要

環境変数の設定

このアプリケーションの実行には、apps/web/src/env.tsのスキーマに記述されている通りの環境変数が必要です。 apps/web/.env.localにRESAS APIキーを保存してください。

RESAS_API_KEY=QwErTy*************

各種タスクの実行

このモノレポ内の各パッケージに対して、Turborepo turboを用いてキャッシュを効かせながら効率的にタスクを実行できます。 pnpm--filter -Fフラグと同じ構文で、実行対象のパッケージを狭めることができます。

pnpm turbo build # 全てのパッケージをビルド
pnpm turbo -F web build # Next.jsのパッケージのみビルド
pnpm turbo -F web dev # Next.jsの開発サーバーを起動
pnpm turbo lint # 全てのパッケージをリント
pnpm turbo test # 全てのパッケージのテストを実行
pnpm turbo sb:test # Storybookのインタラクションテストを実行
pnpm turbo playwright:test # E2Eテストを実行

評価

開発にかかった時間: 6日間 (1日あたり平均5時間作業)

なお、担当者からのレビューは以下の通りです。 よろしければ参考までにご確認をいただけますと幸いです。

Goodチェック

  • 独自にワイヤーフレームを解釈してデザイン・実装している
  • API で取得したデータをキャッシュしている
  • API のエラーハンドリングができている
  • 通信時のローディングの UI を実装している
  • 良いインタラクションを与えるアニメーションを実装している
  • Lighthouse のスコアで高い評価となっている
  • コンポーネント分割の粒度が適切である
  • ビジネスロジックをコンポーネントから外だししている
  • CSS in JS を利用している
  • Unit Test を書いている
  • E2E Test を書いている
  • StoryBook を導入している
  • スナップショットテストが導入されている
  • Docker を利用している
  • CI を構築している
  • Issue や PR の機能などを活用して開発している
  • Hooks を使っている
  • API-key をアプリケーションコードから秘匿している
  • API-key をビルドファイルから秘匿している
  • JSDoc を書いている
  • コメントの量が適切である
  • コミットの粒度が適切である
  • コミットのメッセージが適切である
  • コミットに prefix がついている
  • Turborepo を使用している
  • アイコンライブラリを使用している
  • Zod を使用している
  • Next 14 の App Router を使用している
  • Storybook を活用した Interaction Test を実装している
  • ダークモード対応をしている
  • OGP 対応をしている
  • favicon の設定をしている
  • .npmrc の設定をしている
  • LICENSE の設定をしている
  • .prototools で Node.js と pnpm のバージョン指定をしている
  • ワークスペースファイルを設定している
  • Renovate を導入している
  • Figma を活用している
  • アクセシビリティ対応をしている
  • トップページに人口比較のためのサンプルリンクを設置している
  • Server Component を使用して API への fetch をサーバー側で実行している
  • 実装の各所で多くの工夫が見られクオリティの高いアプリケーションになっている
    • クエリパラメータによるビューの共有
    • 独自のデザイン
    • 適切なメタデータの設定
    • etc…(書ききれない)
  • README.md が詳細にかかれており、アピールポイントや技術スタックが非常にわかりやすい
  • CI/CD を実装したうえでしっかりと全て通っている
  • テストのクオリティが高い
    • E2E テストでグラフが適切に表示されているか検証されている
    • ユニットテストもしっかりとテストデータを用いて細かく検証されている
  • セマンティックな HTML がかけている

Nextチェック

  • チェックボックス横のラベルにホバーした時に cursor: pointer になっていない
  • トップページでチェックボックスをクリックしても表示が変わらない

総合評価

 Figma での UI デザイン設計に始まり、アプリケーションの設計はもちろん、実装意図を残したコメントや各テストの記述など、全てにおいて細部まで丁寧に実装されており、最善を目指して開発される姿勢がとても素晴らしいと思いました。極めて高レベルな対応を 30 時間という短い時間で成し遂げられており、完成した Web アプリケーションもクオリティの高いものになっており、レビュワー一同大変感心いたしました。チーム開発への意識もしっかりとされており、現時点で業務に加わっても第一線で活躍できる素養をお持ちの方だと確信いたしました。  Next 項目もほとんどなかったですが、一点、ユーザー視点に立って Next を上げるとすれば、トップページで都道府県を選択するチェックボックスがあるものの、チェックを付けても何も表示が変わらないのはユーザーフレンドリーではないと感じました。ここを改善されるとより良い Web アプリケーションになるかと思います。

レビュワー一同、非常に好評価でした。

simple-resas-app's People

Contributors

renovate[bot] avatar reohakase avatar

Stargazers

 avatar  avatar

Watchers

 avatar

simple-resas-app's Issues

RESAS(地域経済分析システム) APIの「都道府県一覧」APIから都道府県コード`prefCode`を取得するようにする

Current

prefCodeのスキーマに想定される都道府県コードをハードコードしている

Expected

スキーマはあくまで自然数文字列であることのみを判別し、実際の都道府県コードはRESAS APIからフェッチする

参照: https://opendata.resas-portal.go.jp/docs/api/v1/prefectures.html


要件を見落としていた...

チェックボックス`<Checkbox>`を実装する

<Checkbox>

スタイルが付加されたチェックボックス

<PrefectureCheckbox>

都道府県コードprefCodeとラベルの文字列を受け取り、値が変わるとそれに合わせてsearchParamsを変化させるコンポーネント

Expected Behavior

e.g. <PrefectureCheckbox prefCode={'8'} label="茨城県">の場合
チェックされると?prefCodes8を追加、外されると削除

image

ディレクトリ構造を見直す

概要

  • 各コンポーネントのフォルダに再exportするindex.tsを設けて、importパスを簡略化する
    • 外部から参照されたくないexportも示せる利点あり

devcontainerの設定を更新する

概要

  • Vitestの拡張機能を追加する
  • forwardedPortsに色々追加する
  • Playwrightのインストールコマンドを自動で実行するようにする
  • その他

`<PrefectureCheckbox>`の値がOptimistic updateされるようにする

概要

現状の問題点

都道府県チェックボックス<PrefectureCheckbox>の値を押して変更しても、サーバー側でRSCがレンダーされて返却されるまでURLが書きかわらない。そのため、瞬時にチェックボックスの値が更新されない。また、URLが書き変わる前に再度他のチェックボックス<PrefectureCheckbox>を押しても、遷移先が最初の都道府県チェックボックスによる値を含まないものになってしまう。

解決法

1. /[statLabel]のfetch処理を<Suspense>内に移す

サーバー側の修正では対応不可能

  • generateMetadata()内でもfetch処理を行っており、これは値が解決されるまでのフォールバックを設定できない。 vercel/next.js#45418
  • searchParamsのみを更新する遷移では、loading.tsxで設定した<Suspense>バウンダリは呼び出されない。 vercel/next.js#53543

2. <PrefectureCheckbox>にステートを追加してOptimistic Updateを実装する

<PrefectureCheckbox>の間で共有ステートを作る必要がある。

  • Context
  • Jotai
  • 親Client Componentを作り、親からイベントハンドラを渡す

RESAS APIから人口構成を取得する関数群を実装する

src/infra/resas/fetchPopulationComposition.ts

  • RESAS APIのエンドポイントを唯一叩く関数。APIキーの参照はここに限る。

src/libs/getPopulationCompositionAll.ts

  • ↑を並列実行する関数

src/libs/extractDataPointsByStatLabel.ts

  • ↑の結果を、プロットする際に用いるデータ点の配列に整形する関数
type DataPoint = {
  year: Year;
} & Record<PrefCode, number>;

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Warning

These dependencies are deprecated:

Datasource Name Replacement PR?
npm @storybook/testing-library Unavailable

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

  • chore(): update pnpm to v8.15.9
  • chore(web): update devdependencies (@babel/core, @next/env, @pandacss/dev, @pandacss/preset-panda, @playwright/test, @storybook/addon-a11y, @storybook/addon-actions, @storybook/addon-essentials, @storybook/addon-interactions, @storybook/addon-links, @storybook/addon-viewport, @storybook/blocks, @storybook/nextjs, @storybook/react, @storybook/test, @storybook/test-runner, jsdom, lefthook, playwright, postcss, prettier, storybook, tsup, turbo, typescript, webpack)
  • fix(eslint-config-custom-next): update minor dependencies (@next/eslint-plugin-next, @pandacss/dev, @t3-oss/env-nextjs, @types/node, @typescript-eslint/eslint-plugin, @typescript-eslint/parser, eslint-config-next, eslint-config-turbo, eslint-plugin-react, lucide-react, next, pnpm)
  • chore(): update dependency vitest to v2
  • Click on this checkbox to rebase all open PRs at once

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

devcontainer
.devcontainer/devcontainer.json
  • ghcr.io/devcontainers/features/github-cli 1
  • ghcr.io/NicoVIII/devcontainer-features/pnpm 2
  • ghcr.io/stuartleeks/dev-container-features/shell-history 0
  • ghcr.io/devcontainers/features/node 1
  • ghcr.io/devcontainers-contrib/features/act 1
  • ghcr.io/devcontainers-contrib/features/exa 1
  • ghcr.io/devcontainers-contrib/features/fish-apt-get 1
  • ghcr.io/devcontainers-contrib/features/neofetch 1
  • ghcr.io/devcontainers-contrib/features/starship 1
github-actions
.github/workflows/turbo_build.yml
  • actions/checkout v4
  • moonrepo/setup-toolchain v0
  • actions/cache v4
.github/workflows/turbo_lint.yml
  • actions/checkout v4
  • moonrepo/setup-toolchain v0
  • actions/cache v4
.github/workflows/turbo_playwright:test.yml
  • actions/checkout v4
  • moonrepo/setup-toolchain v0
  • actions/cache v4
  • actions/upload-artifact v4
.github/workflows/turbo_sb:test.yml
  • actions/checkout v4
  • moonrepo/setup-toolchain v0
  • actions/cache v4
.github/workflows/turbo_test.yml
  • actions/checkout v4
  • moonrepo/setup-toolchain v0
  • actions/cache v4
npm
apps/web/package.json
  • @radix-ui/react-select 2.1.1
  • @t3-oss/env-nextjs 0.10.1
  • @types/node 20.14.9
  • @types/react 18.3.3
  • @types/react-dom 18.3.0
  • @vercel/analytics 1.3.1
  • eslint-config-next 14.2.4
  • lucide-react 0.399.0
  • next 14.2.4
  • next-themes 0.3.0
  • pnpm 8.15.8
  • react 18.3.1
  • react-dom 18.3.1
  • recharts 2.12.7
  • zod 3.23.8
  • @babel/core 7.24.7
  • @funboxteam/optimizt 5.0.2
  • @next/env 14.2.4
  • @pandacss/dev 0.41.0
  • @pandacss/preset-panda 0.41.0
  • @playwright/test 1.45.0
  • @radix-ui/colors 3.0.0
  • @storybook/addon-a11y 8.1.11
  • @storybook/addon-actions 8.1.11
  • @storybook/addon-essentials 8.1.11
  • @storybook/addon-interactions 8.1.11
  • @storybook/addon-links 8.1.11
  • @storybook/addon-viewport 8.1.11
  • @storybook/blocks 8.1.11
  • @storybook/nextjs 8.1.11
  • @storybook/react 8.1.11
  • @storybook/test 8.1.11
  • @storybook/test-runner 0.19.0
  • @storybook/testing-library 0.2.2
  • @testing-library/react 16.0.0
  • @vitejs/plugin-react 4.3.1
  • autoprefixer 10.4.19
  • axe-playwright 2.0.1
  • critters 0.0.24
  • jsdom 24.1.0
  • mdx 0.3.1
  • postcss 8.4.38
  • storybook 8.1.11
  • vite-tsconfig-paths 4.3.2
  • vitest 1.6.0
  • webpack 5.92.1
package.json
  • concurrently 8.2.2
  • lefthook 1.6.18
  • patch-package 8.0.0
  • playwright 1.45.0
  • prettier 3.3.2
  • tsup 8.1.0
  • turbo 2.0.6
  • typescript 5.5.2
  • vitest 1.6.0
  • pnpm 8.15.8
packages/eslint-config-custom-next/package.json
  • @next/eslint-plugin-next 14.2.4
  • @pandacss/eslint-plugin 0.1.9
  • @typescript-eslint/eslint-plugin 7.14.1
  • @typescript-eslint/parser 7.14.1
  • eslint-config-airbnb 19.0.4
  • eslint-config-airbnb-typescript 18.0.0
  • eslint-config-next 14.2.4
  • eslint-config-turbo 2.0.6
  • eslint-config-prettier 9.1.0
  • eslint-plugin-import 2.29.1
  • eslint-plugin-jsx-a11y 6.9.0
  • eslint-plugin-react 7.34.3
  • eslint-plugin-react-hooks 4.6.2
  • eslint-plugin-storybook 0.8.0
packages/eslint-config-custom/package.json
  • @typescript-eslint/eslint-plugin 7.14.1
  • @typescript-eslint/parser 7.14.1
  • eslint-config-airbnb-base 15.0.0
  • eslint-config-airbnb-typescript 18.0.0
  • eslint-config-turbo 2.0.6
  • eslint-config-prettier 9.1.0
  • eslint-plugin-import 2.29.1
packages/panda-preset-radix-colors/package.json
  • @pandacss/dev 0.41.0
  • pandacss-preset-radix-colors 0.2.0
packages/panda-preset-radix-ui/package.json
  • @pandacss/dev 0.41.0
packages/tsconfig/package.json

  • Check this box to trigger a request for Renovate to run again on this repository

`/[statLabel]`ページのタイトル表示部分をReact Server Componentに切り分けて、ローディング表示を追加する

概要

現状

タイトル表示文字列を生成するために行っているfetchが終わるまで、ローディング画面の返却が行えていない。

理想

src/app/[statLabel]/page.tsxでのfetch処理の実行をやめて、<Suspense>で囲う。
しかし、結局generateMetadata()関数内でもfetchしているため、修正してもパフォーマンスの改善は望めないかもしれない。

グラフを表示するコンポーネント`<Chart>`を実装する

概要

以下の型を持つデータ点の配列とその他表示用文字列を受け取って、グラフを表示するコンポーネントを作成する

export const dataPointValueRecordSchema = z.record(prefCodeSchema, z.number().min(0).nullable());
export type DataPointValueRecord = z.infer<typeof dataPointValueRecordSchema>;

export type DataPoint = {
  year: Year;
} & DataPointValueRecord;

参照

トップページに説明と提案リンクを追加する

概要

以下の文章とリンクをトップページに追加する

RESAS(地域経済分析システム)に掲載されている各種人口データを、都道府県別にグラフで比較できます。
株式会社ゆめみのフロントエンド課題の一環で白田連大 @ReoHakaseにより作成されました。
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.