週の7日のうち、52時間だけ注文を受け付ける。
洋菓子店のルールをコードで表現するとき、「時間外はフォームを見せない」という設計が必要だった。ただ「受付期間外です」と表示するだけでなく、「次はいつ注文できるのか」も伝える。不便を感じたお客さんに「また来てください」という気持ちを届けるために。
52時間の境界を判定する
受付期間は「火曜の20時ちょうどから木曜の20時ちょうどまで」だ。境界が時刻を跨いでいるため、曜日だけでは判断できない。
function isAcceptingOrders() {
const now = new Date();
const day = now.getDay();
const hour = now.getHours();
const min = now.getMinutes();
const timeVal = hour * 60 + min;
if (day === 2 && timeVal >= 20 * 60) return true; // 火曜20時以降
if (day === 3) return true; // 水曜は全日
if (day === 4 && timeVal < 20 * 60) return true; // 木曜20時前
return false;
}
月曜・火曜20時前は受付前。金曜・土曜・日曜は期間後。木曜20時以降も期間外。
この関数がfalseを返したとき、フォームの代わりに「現在受付期間外です」という画面を表示する。そしてもう一つ、次の受付開始日時を表示する。
次の火曜20時を計算する
お客さんが期間外に来たとき、「次はいつ?」という疑問への答えを自動で出す。
function getNextAcceptStart() {
const now = new Date();
const day = now.getDay();
const hour = now.getHours();
let daysUntilTue;
if (day < 2) {
daysUntilTue = 2 - day; // 日曜・月曜 → 今週火曜
} else if (day === 2 && hour < 20) {
daysUntilTue = 0; // 火曜20時前 → 今日の20時
} else {
daysUntilTue = 9 - day; // 木曜20時以降〜月曜 → 翌週火曜
}
const next = new Date(now);
next.setDate(now.getDate() + daysUntilTue);
next.setHours(20, 0, 0, 0);
return `${next.getMonth()+1}月${next.getDate()}日`;
}
「現在受付期間外です。次回受付:6月10日(火)20:00〜」という表示が出る。お客さんはカレンダーにメモして、また来てくれる。
LPに受付状況を常時表示する
フォームを開くまで「今注文できるかどうか」が分からない、という設計にしなかった。
LPのトップに受付状況バッジを置いた。受付中なら緑で「受付中 〜 木曜20:00まで」、期間外なら灰色で「次回受付:○月○日(火)20:00〜」が常時表示される。
サイトを開いた瞬間に状況が分かる。「注文しようとしたら期間外だった」という体験が減る。問い合わせも減る。
GAS側でも判定する理由
フロントエンドのJavaScriptは、技術的には書き換えられる。「受付期間外だけど、なんとかフォームを送ってみよう」というアクセスも理論上は可能だ。
GASの処理の先頭で、もう一度受付期間を確認する。
function submitOrder(data) {
if (!isAcceptingOrders_GAS()) {
return { success: false, error: '受付期間外です' };
}
// ...
}
GAS側ではnew Date()がUTCで返ることに注意が必要だ。日本時間(JST)で判定するために、toLocaleStringでJSTに変換してから曜日・時刻を評価する。
フロントエンドとGASで同じルールを二重に持つ。これは冗長に見えるが、「ユーザーが見るルール」と「サーバーが守るルール」は別物として扱う方が安全だ。
*次回は「ブランドデザインとUI——クリーム×ゴールドのCormorant Garamondで作る」*
*シンプルシステム株式会社 代表 伊藤勝彦*