フォームブリッジでの日付入力制御について

フォームブリッジで賃貸解約フォームを作っています。

解約日と立会希望日を作っているのですが、次のような生業を掛けたいと考えています。

① 解約日では、本日から1か月後以降しか選択できない設定

② 立会希望日では、本日から解約日までの選択肢かつ、弊社指定日が選択できない

この2点制御を掛けたいのですが、上手くいきません。

制御する方法をご教授いただけますと大変有り難く思います。宜しくお願いします。

コードをここに入力または貼り付け

前提として:フィールドコードとフィールタイプ

したこと

ChatGPTのGPTsに(JavaScriptカスタマイズ | FormBridge)の内容を知識として入れて、プロンプトに質問内容を貼り付けた。

検討課題

  • 弊社指定日のデータをどのように持たせるか?
  • ユーザーにどのように見せるか?
  • 日付を選択するカレンダー画面で見やすくしたい場合は、Formbridge標準以外のカレンダーを使う必要がある。

コード

// === 設定ここから ===
const CANCEL_DATE = "cancel_date"; // 解約日フィールドコード
const MEETING_DATE = "meeting_date"; // 立会希望日フィールドコード

// 立会の「弊社指定の選択不可日」(YYYY-MM-DD) で列挙
const BLACKOUT_DATES = new Set(["2026-03-10", "2026-03-15", "2026-03-20"]);
// === 設定ここまで ===

// 日付ユーティリティ
function toYMD(d) {
	const y = d.getFullYear();
	const m = String(d.getMonth() + 1).padStart(2, "0");
	const day = String(d.getDate()).padStart(2, "0");
	return `${y}-${m}-${day}`;
}
function parseYMD(s) {
	// s は "YYYY-MM-DD" 想定(FormBridgeのDATEの一般的形式)
	if (!s) return null;
	const [y, m, d] = s.split("-").map(Number);
	const dt = new Date(y, m - 1, d);
	// 不正日付対策(NaNなど)
	return Number.isNaN(dt.getTime()) ? null : dt;
}
function addMonths(date, months) {
	const d = new Date(date);
	const day = d.getDate();
	d.setMonth(d.getMonth() + months);

	// 1/31 + 1month -> 3/3 みたいなズレ対策(末日丸め)
	if (d.getDate() < day) d.setDate(0);
	return d;
}
function startOfToday() {
	const now = new Date();
	return new Date(now.getFullYear(), now.getMonth(), now.getDate());
}

function setErrorAndClear(context, fieldCode, message) {
	context.setFieldValueError(fieldCode, message);
	context.preventDefault();
	context.setFieldValue(fieldCode, ""); // DATEは空文字でクリアされる想定
}

// ① 解約日:本日+1か月以降のみ
formBridge.events.on(`form.field.change.${CANCEL_DATE}`, (context) => {
	const today = startOfToday();
	const minCancel = addMonths(today, 1); // 本日から1か月後
	const minCancelYMD = toYMD(minCancel);

	const cancelStr = context.value; // 変更後の値
	const cancelDate = parseYMD(cancelStr);

	// 入力クリアは許容(必須なら別途必須設定/submit時チェック)
	if (!cancelDate) {
		context.setFieldValueError(CANCEL_DATE, null);
		return;
	}

	if (toYMD(cancelDate) < minCancelYMD) {
		setErrorAndClear(
			context,
			CANCEL_DATE,
			`解約日は ${minCancelYMD} 以降を選択してください。`,
		);
		return;
	}

	// エラー解除
	context.setFieldValueError(CANCEL_DATE, null);

	// 解約日が変わったので、立会希望日が範囲外になっていないか再チェック
	const record = formBridge.fn.getRecord();
	const meetingStr = record[MEETING_DATE]?.value;
	const meetingDate = parseYMD(meetingStr);

	if (meetingDate) {
		const todayYMD = toYMD(today);
		const cancelYMD = toYMD(cancelDate);
		const meetingYMD = toYMD(meetingDate);

		if (
			meetingYMD < todayYMD ||
			meetingYMD > cancelYMD ||
			BLACKOUT_DATES.has(meetingYMD)
		) {
			// 立会希望日をクリアし、ユーザーに理由を表示
			context.setFieldValueError(
				MEETING_DATE,
				"立会希望日が解約日変更により無効になったため、再選択してください。",
			);
			context.setFieldValue(MEETING_DATE, "");
		} else {
			context.setFieldValueError(MEETING_DATE, null);
		}
	}
});

// ② 立会希望日:本日〜解約日、かつ指定日不可
formBridge.events.on(`form.field.change.${MEETING_DATE}`, (context) => {
	const today = startOfToday();
	const todayYMD = toYMD(today);

	const meetingStr = context.value;
	const meetingDate = parseYMD(meetingStr);

	if (!meetingDate) {
		context.setFieldValueError(MEETING_DATE, null);
		return;
	}

	const record = formBridge.fn.getRecord();
	const cancelStr = record[CANCEL_DATE]?.value;
	const cancelDate = parseYMD(cancelStr);

	if (!cancelDate) {
		setErrorAndClear(context, MEETING_DATE, "先に解約日を入力してください。");
		return;
	}

	const meetingYMD = toYMD(meetingDate);
	const cancelYMD = toYMD(cancelDate);

	if (meetingYMD < todayYMD || meetingYMD > cancelYMD) {
		setErrorAndClear(
			context,
			MEETING_DATE,
			`立会希望日は ${todayYMD} 〜 ${cancelYMD} の範囲で選択してください。`,
		);
		return;
	}

	if (BLACKOUT_DATES.has(meetingYMD)) {
		setErrorAndClear(
			context,
			MEETING_DATE,
			"選択できない指定日です。別日を選択してください。",
		);
		return;
	}

	context.setFieldValueError(MEETING_DATE, null);
});

ありがとうございました。早速試させていただきます。

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。