import React, { useEffect, useMemo, useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import {
Camera,
Sparkles,
Refrigerator,
ShoppingBag,
Send,
CheckCircle2,
Clock3,
Users,
Soup,
Milk,
Egg,
Beef,
Leaf,
MessageCircle,
ChevronRight,
RotateCcw,
Heart,
Bell,
Plus,
Minus,
Home,
Utensils,
Gift,
} from "lucide-react";
const steps = [
{ key: "home", label: "ホーム" },
{ key: "capture", label: "撮影" },
{ key: "analyzing", label: "AI解析" },
{ key: "inventory", label: "在庫" },
{ key: "recipes", label: "献立" },
{ key: "request", label: "買ってキテ" },
{ key: "family", label: "家族側" },
];
const detectedItemsBase = [
{ id: 1, name: "卵", note: "残り 4個くらい", confidence: 94, icon: Egg, tag: "朝食にも" },
{ id: 2, name: "牛乳", note: "少なめかも", confidence: 87, icon: Milk, tag: "期限注意" },
{ id: 3, name: "豚こま", note: "1パック", confidence: 82, icon: Beef, tag: "今日使いたい" },
{ id: 4, name: "キャベツ", note: "半玉くらい", confidence: 89, icon: Leaf, tag: "野菜" },
{ id: 5, name: "納豆", note: "3パック", confidence: 78, icon: Soup, tag: "定番" },
];
const recipes = [
{
title: "豚こまキャベツ炒め",
badge: "買い足しなし",
time: "10分",
desc: "豚こま・キャベツ・卵で、今日すぐ作れる節約メニュー。",
ingredients: ["豚こま", "キャベツ", "卵"],
},
{
title: "豆腐だけ買えば麻婆豆腐",
badge: "豆腐だけ買ってキテ",
time: "15分",
desc: "帰り道の家族に豆腐だけ頼めば、夕食のメインが完成。",
ingredients: ["豚こま", "豆腐", "ねぎ"],
recommended: true,
},
{
title: "子ども向けチーズオムレツ",
badge: "子ども向け",
time: "8分",
desc: "卵と牛乳でふんわり。冷蔵庫にチーズがあればさらに◎。",
ingredients: ["卵", "牛乳", "チーズ"],
},
];
function cx(...classes) {
return classes.filter(Boolean).join(" ");
}
function Logo() {
return (
Katteキテ
AI fridge family app
);
}
function PhoneShell({ children }) {
return (
);
}
function AppHeader({ step, goTo }) {
return (
{steps.slice(0, 7).map((s) => (
x.key === step) >= steps.findIndex((x) => x.key === s.key)
? "bg-orange-400"
: "bg-orange-100"
)}
/>
))}
);
}
function FridgeIllustration({ scanning = false }) {
const foods = [
{ label: "MILK", className: "left-[12%] top-[14%] h-20 w-12 bg-blue-100" },
{ label: "EGG", className: "left-[34%] top-[17%] h-11 w-24 bg-amber-100" },
{ label: "MEAT", className: "left-[13%] top-[47%] h-12 w-28 bg-rose-100" },
{ label: "VEG", className: "left-[53%] top-[43%] h-16 w-24 bg-emerald-100" },
{ label: "NATTO", className: "left-[57%] top-[18%] h-12 w-20 bg-yellow-100" },
];
return (
{foods.map((food) => (
{food.label}
))}
{scanning && (
)}
);
}
function HomeScreen({ goTo }) {
return (
冷蔵庫を1枚撮るだけ
今日のごはんと、
買い足しが決まる。
冷蔵庫の中身をAIがざっくり読み取り。献立・不足食材・家族への買い物依頼まで、30秒で完了。
{[
[Camera, "撮る"],
[Utensils, "決まる"],
[Send, "頼める"],
].map(([Icon, label]) => (
))}
);
}
function CaptureScreen({ goTo }) {
return (
冷蔵庫を撮影
完璧に写らなくてもOK。見える食材をAIが候補として出します。
);
}
function AnalyzingScreen({ goTo }) {
const messages = ["食材を読み取り中…", "似ている商品を照合中…", "献立候補を考え中…"];
const [messageIndex, setMessageIndex] = useState(0);
useEffect(() => {
const msgTimer = setInterval(() => {
setMessageIndex((v) => (v + 1) % messages.length);
}, 850);
const timer = setTimeout(() => goTo("inventory"), 3200);
return () => {
clearInterval(msgTimer);
clearTimeout(timer);
};
}, [goTo]);
return (
);
}
function InventoryScreen({ goTo }) {
const [items, setItems] = useState(detectedItemsBase.map((item) => ({ ...item, active: true })));
const toggleItem = (id) => {
setItems((current) => current.map((item) => (item.id === id ? { ...item, active: !item.active } : item)));
};
return (
AIが見つけた食材
違っていたらワンタップで修正。完璧な在庫表は目指しません。
{items.map((item) => {
const Icon = item.icon;
return (
);
})}
);
}
function RecipesScreen({ goTo }) {
return (
今日作れるごはん
家族の好み・調理時間・買い足し最小をもとに3つだけ提案。
{recipes.map((recipe) => (
{recipe.badge}
{recipe.time}
{recipe.title}
{recipe.desc}
{recipe.recommended && (
)}
{recipe.ingredients.map((ingredient) => (
{ingredient}
))}
))}
);
}
function RequestScreen({ goTo }) {
const [sent, setSent] = useState(false);
return (
家族に買ってキテ
料理に足りない食材だけを、家族にワンタップ共有。
豆腐だけ買ってキテ
冷蔵庫の豚こまと合わせて、麻婆豆腐にする予定!
);
}
function FamilyScreen({ goTo }) {
const [status, setStatus] = useState("unread");
const statusView = useMemo(() => {
if (status === "bought") return { text: "買ったよ!", color: "emerald", icon: CheckCircle2 };
if (status === "alt") return { text: "木綿豆腐がなかったので絹豆腐にしたよ", color: "orange", icon: ShoppingBag };
if (status === "none") return { text: "売ってなかった…", color: "slate", icon: Minus };
return null;
}, [status]);
return (
頼まれた側は、買えたかどうかをワンタップで返せます。
妻
豆腐だけ買ってキテ
麻婆豆腐にする予定!1丁あればOK。
{status === "unread" ? (
) : (
{(() => {
const Icon = statusView.icon;
return ;
})()}
{statusView.text}
料理担当にも自動で共有されました
)}
);
}
function ScreenWrap({ children }) {
return (
{children}
);
}
function SidePanel({ goTo }) {
const cards = [
{
icon: Camera,
title: "撮るだけで始まる",
text: "手入力ではなく、冷蔵庫の写真を入口にするから利用ハードルが低い。",
},
{
icon: Sparkles,
title: "完璧な在庫表を目指さない",
text: "AIのざっくり認識+ワンタップ修正で、日常利用に寄せる。",
},
{
icon: Users,
title: "家族共有がコア機能",
text: "買い物担当と料理担当をつなぎ、家庭内の小さなストレスを減らす。",
},
{
icon: Gift,
title: "将来の収益化余地",
text: "家族プレミアム、レシートポイント、送客、匿名統計データ活用へ拡張。",
},
];
return (
社内提案用 UI/UXモック
冷蔵庫管理ではなく、
家族の買い物OSへ。
Katteキテは、スマホで冷蔵庫を撮るだけで「今日作れるもの」「足りないもの」「家族に頼むもの」をつなげるアプリの体験モックです。
{cards.map((card) => {
const Icon = card.icon;
return (
);
})}
MVPで検証する導線
{[
"冷蔵庫撮影",
"AI解析",
"ワンタップ修正",
"献立提案",
"買ってキテ共有",
"家族の完了報告",
].map((label, index) => (
{label}
{index < 5 && }
))}
);
}
export default function KatteKiteMock() {
const [step, setStep] = useState("home");
const goTo = (next) => setStep(next);
const CurrentScreen = {
home: HomeScreen,
capture: CaptureScreen,
analyzing: AnalyzingScreen,
inventory: InventoryScreen,
recipes: RecipesScreen,
request: RequestScreen,
family: FamilyScreen,
}[step];
return (
);
}