// ===== AiPAL CarePlan 外部JS =====
// 必須: ここをあなたのGAS WebアプリURLに置換
const GAS_ENDPOINT = “https://script.google.com/macros/s/XXXXXXXXXXXXXXXX/exec”;

// ユーティリティ
const $ = (id) => document.getElementById(id);

// DOM準備
document.addEventListener(“DOMContentLoaded”, () => {
const state = { planText: “” };

// APIキーUI(任意機能):localStorage保存だけ行う
const KEY_STORAGE = “AIPAL_OPENAI_KEY”;
const keyState = $(“keyState”);
const saved = localStorage.getItem(KEY_STORAGE);
if (saved && keyState) {
keyState.textContent = “保存済み:この端末のみで使用されます。”;
keyState.style.color = “#2b7a0b”;
}

const saveKeyBtn = $(“saveKey”);
if (saveKeyBtn) {
saveKeyBtn.addEventListener(“click”, () => {
const v = ($(“apiKey”)?.value || “”).trim();
if (!v) {
if (keyState) {
keyState.textContent = “未入力です。”;
keyState.style.color = “#b42318”;
}
return;
}
localStorage.setItem(KEY_STORAGE, v);
if ($(“apiKey”)) $(“apiKey”).value = “”;
if (keyState) {
keyState.textContent = “保存しました。以後この端末のブラウザ内で使用します。”;
keyState.style.color = “#2b7a0b”;
}
});
}

// システムプロンプト(オードリー・タン思想)
const SYS = [
“あなたは「本人中心・共創(plurality)」のケアプラン作成アシスタントです。”,
“価値観:透明性・包摂・コラボレーション・当事者参加。判断は事実に基づき、語りを尊重します。”,
“文体:やさしい「です・ます」。否定や矯正語は避け、可能性を開く表現を使います。”,
“出力は観察可能な行動目標(具体・小さな一歩)と、PDCAで更新可能な構造にします。”,
“家族・職員・環境は“支援の共同体”として位置づけ、負担軽減と自律を両立させます。”
].join(“\n”);

// プロンプト生成
function buildUserPrompt() {
const name = $(“p_name”)?.value?.trim() || “”;
const age = $(“p_age”)?.value?.trim() || “”;
const gender = $(“p_gender”)?.value?.trim() || “”;
const dx = $(“p_dx”)?.value?.trim() || “”;
const needs = $(“i_needs”)?.value?.trim() || “”;
const family = $(“i_family”)?.value?.trim() || “”;
const daily = $(“i_daily”)?.value?.trim() || “”;
const adl = $(“i_adl”)?.value?.trim() || “”;
const safety = $(“i_safety”)?.value?.trim() || “”;

return `
【利用者情報】
氏名:${name}
年齢:${age}
性別:${gender}
診断名・留意点:${dx}

【本人の言葉(原文尊重)】
${needs}

【家族の意向・価値観】
${family}

【最近の様子(観察事実・変化)】
${daily}

【ADL/IADL】
${adl}

【安全・医療上の留意点】
${safety}

【出力フォーマット(日本語)】
【本人が大切にしていること】(本人の語りを1〜2文で要約。尊称を使い、評価語を避ける)
【短期目標(1〜3ヶ月)】(観察可能な行動目標を2〜3項目。肯定形・小さな一歩)
【長期目標(6ヶ月〜)】(“その人らしい生活”を1文で)
【支援の方針】
– 職員:1〜2文(伴走・選択肢の提示・環境調整)
– 家族:1〜2文(役割の合意・負担の可視化と軽減)
– 環境:1〜2文(物理/時間/情報のバリアフリー)
【評価の視点(C)】(客観指標×本人の実感:確認頻度の例示)
【次の一手(A)】(改善のための小さな選択肢を箇条書き)
`;
}

// GASリレー経由でOpenAI呼び出し
async function callOpenAI(userContent) {
const res = await fetch(GAS_ENDPOINT, {
method: “POST”,
headers: { “Content-Type”: “application/json” },
body: JSON.stringify({ sys: SYS, user: userContent })
});
if (!res.ok) {
const t = await res.text();
throw new Error(“Relayエラー:” + t);
}
const json = await res.json();
return json?.choices?.[0]?.message?.content || “”;
}

// UIイベント
const btnGen = $(“btnGen”);
const btnPrint = $(“btnPrint”);
const btnJson = $(“btnJson”);
const status = $(“status”);
const resultCard = $(“resultCard”);
const planOut = $(“planOut”);
const pdcaSel = $(“pdca”);

if (btnGen) {
btnGen.addEventListener(“click”, async () => {
if (status) status.textContent = “生成中…”;
btnGen.disabled = true;
if (btnPrint) btnPrint.disabled = true;
if (btnJson) btnJson.disabled = true;
try {
const prompt = buildUserPrompt();
const text = await callOpenAI(prompt);
state.planText = text;
if (planOut) planOut.textContent = text;
if (resultCard) resultCard.style.display = “block”;
if (status) status.textContent = “生成しました。内容を確認してください。”;
if (btnPrint) btnPrint.disabled = false;
if (btnJson) btnJson.disabled = false;
const y = resultCard?.offsetTop ? resultCard.offsetTop – 12 : 0;
window.scrollTo({ top: y, behavior: “smooth” });
} catch (err) {
if (status) status.textContent = “エラー:” + (err?.message || String(err));
} finally {
btnGen.disabled = false;
}
});
}

if (btnPrint) {
btnPrint.addEventListener(“click”, () => window.print());
}

if (btnJson) {
btnJson.addEventListener(“click”, () => {
const data = {
person: {
name: $(“p_name”)?.value?.trim() || “”,
age: $(“p_age”)?.value?.trim() || “”,
gender: $(“p_gender”)?.value?.trim() || “”,
dx: $(“p_dx”)?.value?.trim() || “”
},
input: {
needs: $(“i_needs”)?.value?.trim() || “”,
family: $(“i_family”)?.value?.trim() || “”,
daily: $(“i_daily”)?.value?.trim() || “”,
adl: $(“i_adl”)?.value?.trim() || “”,
safety: $(“i_safety”)?.value?.trim() || “”
},
plan: state.planText,
pdca: pdcaSel?.value || “P”,
createdAt: new Date().toISOString()
};
const blob = new Blob([JSON.stringify(data, null, 2)], { type: “application/json” });
const url = URL.createObjectURL(blob);
const a = document.createElement(“a”);
a.href = url;
const filename = `careplan_${(data.person.name || “noname”)}_${data.createdAt.slice(0, 10)}.json`;
a.download = filename;
document.body.appendChild(a);
a.click();
a.remove();
URL.revokeObjectURL(url);
});
}
});