Mintgreenは、React 19、TypeScript、Vite、Supabaseを使用して構築されたモダンなオンライン投票システムです。
このアプリケーションは、デジタル選挙や投票を安全かつ効率的に実施するためのプラットフォームです。有権者登録から投票、結果表示まで、選挙プロセス全体をサポートします。
- 有権者登録: 身分証明書番号による有権者の登録・管理
- GitHub Issues評価: GitHub Pull Requestsの自動同期と投票機能
- フロントエンド: React 19, TypeScript, Vite
- バックエンド: Supabase (PostgreSQL, Authentication, Real-time)
- ルーティング: React Router DOM
- スタイリング: CSS
- テスト: Vitest, Testing Library
- リンター: Biome
- Node.js (推奨: 18.x以上)
- npm または yarn
- Supabaseアカウント
git clone https://github.com/hideakikondo/mintgreen.git
cd mintgreennpm install.env.exampleファイルを.envにコピーし、Supabaseの認証情報を設定してください:
cp .env.example .env.envファイルを編集し、以下の値を設定:
VITE_SUPABASE_URL=your_supabase_project_url
VITE_SUPABASE_ANON_KEY=your_supabase_anon_key
Supabaseの認証情報は、Supabaseダッシュボードの「Project Settings」→「API」で確認できます。
Supabaseプロジェクトで以下のテーブルを作成してください:
voters(有権者情報)github_issues(GitHub Issues/PRs情報)issue_votes(Issue投票記録)issue_comments(Issueコメント)
npm run devアプリケーションは http://localhost:5174 で利用できます。
# ビルド
npm run build
# プレビュー
npm run preview
# リンター実行
npm run lint
# フォーマット
npm run format
# テスト実行
npm run test
# GitHub PRs同期(手動実行)
npm run sync-prsこのプロジェクトでは、GitHub Actionsを使用して毎日自動的に指定されたリポジトリのPull Requestsを管理し、Supabaseのgithub_issuesテーブルに同期します。
主な機能:
- オープンなPull Requestsの自動同期
- クローズされたPull Requestsの自動削除
- 重複チェックと更新日時による差分同期
-
GitHubリポジトリの「Settings」→「Secrets and variables」→「Actions」で以下のSecretsを設定:
GITHUB_TOKEN: GitHub Personal Access Token (repo権限が必要)SUPABASE_URL: SupabaseプロジェクトのURLSUPABASE_SERVICE_KEY: Supabaseのサービスキー(anon keyではなく)
-
ワークフローは毎日午前9時(UTC)= 日本時間18時に自動実行されます
正確なIssueランキングを高速で取得するため、以下のPostgreSQL関数をSupabaseダッシュボードで実行してください:
CREATE OR REPLACE FUNCTION get_top_ranked_issues(limit_count INT DEFAULT 5)
RETURNS TABLE (
issue_id UUID,
title TEXT,
body TEXT,
github_issue_number INT,
repository_owner TEXT,
repository_name TEXT,
created_at TIMESTAMPTZ,
plus_one_count INT,
minus_one_count INT,
branch_name TEXT,
good_votes INT,
bad_votes INT,
total_good_count INT,
total_bad_count INT,
score INT
)
LANGUAGE plpgsql
AS $$
BEGIN
RETURN QUERY
WITH vote_counts AS (
SELECT
iv.issue_id,
COALESCE(SUM(CASE WHEN iv.vote_type = 'good' THEN 1 ELSE 0 END), 0)::INT as good_votes,
COALESCE(SUM(CASE WHEN iv.vote_type = 'bad' THEN 1 ELSE 0 END), 0)::INT as bad_votes
FROM issue_votes iv
GROUP BY iv.issue_id
)
SELECT
gi.issue_id,
gi.title,
gi.body,
gi.github_issue_number,
gi.repository_owner,
gi.repository_name,
gi.created_at,
gi.plus_one_count,
gi.minus_one_count,
gi.branch_name,
COALESCE(vc.good_votes, 0) as good_votes,
COALESCE(vc.bad_votes, 0) as bad_votes,
(COALESCE(vc.good_votes, 0) + COALESCE(gi.plus_one_count, 0)) as total_good_count,
(COALESCE(vc.bad_votes, 0) + COALESCE(gi.minus_one_count, 0)) as total_bad_count,
(COALESCE(vc.good_votes, 0) + COALESCE(gi.plus_one_count, 0)) -
(COALESCE(vc.bad_votes, 0) + COALESCE(gi.minus_one_count, 0)) as score
FROM github_issues gi
LEFT JOIN vote_counts vc ON gi.issue_id = vc.issue_id
ORDER BY score DESC
LIMIT limit_count;
END;
$$;
-- 権限付与
GRANT EXECUTE ON FUNCTION get_top_ranked_issues TO anon, authenticated;この関数により、全てのIssueを対象とした正確なランキングを効率的に取得できます。関数が利用できない場合は、自動的にクライアント側での計算にフォールバックします。
- 手動実行も可能:「Actions」タブから「Sync GitHub Pull Requests」ワークフローを選択し、「Run workflow」をクリック
現在の監視対象:
team-mirai/policy
他のリポジトリを追加する場合は、scripts/sync-github-prs.jsのREPOSITORIES配列を編集してください。
src/
├── app/ # ページコンポーネント
│ ├── issues/ # GitHub Issues機能
│ └── issue-vote/ # Issue投票機能
├── components/ # 再利用可能なコンポーネント
│ ├── admin/ # 管理者用コンポーネント
│ └── common/ # 共通コンポーネント
├── lib/ # ライブラリとユーティリティ
├── types/ # TypeScript型定義
└── App.tsx # メインアプリケーション
このプロジェクトはApache License 2.0の下でライセンスされています。詳細はLICENSEファイルをご覧ください。