posimai-tech-events/api/events.js

172 lines
7.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Posimai Events - /api/events
*
* GET /api/events -> イベント一覧を返す(モックデータ or KVストア
* POST /api/events -> n8n から構造化データを受け取り保存するエンドポイント
*
* 現在はモックデータを返す。
* n8n 連携時は EVENTS_STORE_TOKEN を環境変数に設定し、
* POST で受け取ったデータを Vercel KV または外部DBへ書き込む実装に差し替える。
*/
const MOCK_EVENTS = [
{
id: '1',
title: '春の産直マルシェ',
startDate: '2026-03-03', startTime: '09:00',
endDate: '2026-03-05', endTime: '16:00',
location: '市民広場 イベントスペース',
address: '○○市中央1-1',
description: '地元農家が丹精込めて育てた旬の野菜・果物が並ぶ春の産直市。パン工房や手作りスイーツのブースも出店。家族でゆっくり楽しめます。',
category: 'マルシェ',
url: 'https://example.com/marche',
source: '市役所公式サイト'
},
{
id: '2',
title: '朝の太極拳教室(無料体験)',
startDate: '2026-03-03', startTime: '07:00',
endDate: '2026-03-03', endTime: '08:30',
location: '中央公園 芝生広場',
address: '○○市中央公園',
description: '毎週火・木・土曜開催の太極拳サークルが無料体験会を開催。初心者・シニアの方歓迎。動きやすい服装でお越しください。',
category: '体験・スポーツ',
url: 'https://example.com/taichi',
source: '地域掲示板'
},
{
id: '3',
title: '防災訓練・地域説明会',
startDate: '2026-03-05', startTime: '10:00',
endDate: '2026-03-05', endTime: '12:00',
location: '○○公民館 大ホール',
address: '○○市西町2-5',
description: '年1回の地区防災訓練と、今年度の避難計画変更に関する説明会を同日開催します。参加無料。',
category: '地域・行政',
url: 'https://example.com/bousai',
source: '町内会回覧板'
},
{
id: '4',
title: '伝統工芸・陶芸ワークショップ',
startDate: '2026-03-06', startTime: '13:00',
endDate: '2026-03-06', endTime: '17:00',
location: '○○文化センター 工芸室',
address: '○○市文化通り3-8',
description: '地元陶芸家による手びねり体験。土から形を作り、釉薬を選んで焼き上げ後日お渡し。定員12名・要事前申込。参加費 2,500円。',
category: 'ワークショップ',
url: 'https://example.com/ceramics',
source: '文化センターHP'
},
{
id: '5',
title: '春のクラフトフェア 2026',
startDate: '2026-03-07', startTime: '10:00',
endDate: '2026-03-08', endTime: '17:00',
location: '○○公園 野外広場',
address: '○○市北公園',
description: '全国から集まるクラフト作家80組が出展。アクセサリー、革工芸、テキスタイル、木工など多彩なジャンル。フードトラックも10台出店。入場無料。',
category: 'マーケット',
url: 'https://example.com/craft',
source: '実行委員会HP'
},
{
id: '6',
title: '地域清掃ボランティア',
startDate: '2026-03-08', startTime: '09:00',
endDate: '2026-03-08', endTime: '11:00',
location: '○○川 河川敷',
address: '○○市河川敷公園',
description: '春の清掃活動。参加自由・事前申込不要。軍手・ゴミ袋は主催者が用意。終了後、軽食の提供あり。',
category: '地域・ボランティア',
url: 'https://example.com/cleanup',
source: '市環境課HP'
},
{
id: '7',
title: '春のクラシックコンサート',
startDate: '2026-03-14', startTime: '15:00',
endDate: '2026-03-14', endTime: '17:30',
location: '○○市民ホール 小ホール',
address: '○○市文化町1-1',
description: '地元弦楽四重奏団による春のコンサート。ハイドン・シューベルトを中心に演奏。全席自由・入場料 1,000円高校生以下無料。',
category: '音楽・アート',
url: 'https://example.com/concert',
source: '市民ホールHP'
},
{
id: '8',
title: 'まちなかマルシェ4月',
startDate: '2026-04-04', startTime: '10:00',
endDate: '2026-04-05', endTime: '16:00',
location: '商店街アーケード',
address: '○○市本町通り',
description: '毎月第1土日開催の定期マルシェ。4月は春のテーマで出店者募集中出店費無料。',
category: 'マルシェ',
url: 'https://example.com/monthly',
source: '商店街組合HP'
},
{
id: '9',
title: '子ども映画祭(無料上映)',
startDate: '2026-02-28', startTime: '10:00',
endDate: '2026-03-02', endTime: '17:00',
location: '中央図書館 多目的ホール',
address: '○○市図書館通り',
description: '国内外の子ども向けアニメ・映画の無料上映会。3日間で10作品上映。入場無料・予約不要。',
category: '映画・文化',
url: 'https://example.com/film',
source: '図書館HP'
},
{
id: '10',
title: '早春の野鳥観察会',
startDate: '2026-03-01', startTime: '07:00',
endDate: '2026-03-01', endTime: '09:30',
location: '○○自然公園 入口',
address: '○○市郊外 自然公園',
description: '自然観察指導員が案内するバードウォッチング入門ツアー。双眼鏡の貸し出しあり。申込不要。',
category: '自然・体験',
url: 'https://example.com/birds',
source: '環境教育センターHP'
}
];
export default function handler(req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
if (req.method === 'OPTIONS') {
return res.status(200).end();
}
if (req.method === 'GET') {
return res.status(200).json({
events: MOCK_EVENTS,
updatedAt: new Date().toISOString(),
source: 'mock'
});
}
// POST: n8n からのデータ受信エンドポイント(プロトタイプでは受け入れのみ)
if (req.method === 'POST') {
const token = process.env.EVENTS_STORE_TOKEN;
const authHeader = req.headers['authorization'];
if (token && authHeader !== `Bearer ${token}`) {
return res.status(401).json({ error: 'Unauthorized' });
}
const body = req.body;
// TODO: Vercel KV または外部DBへの書き込みをここに実装する
// const { kv } = require('@vercel/kv');
// await kv.set(`event:${body.id}`, JSON.stringify(body));
console.log('Received event from n8n:', JSON.stringify(body));
return res.status(200).json({ ok: true, received: true });
}
return res.status(405).json({ error: 'Method not allowed' });
}