猫を管理しするアプリになります。
制作理由
猫の管理が疎かになり体調管理や食生活が不規則になりやすく、病気になりにくく対処がしやすいので、普段からの体調を監視しておくとことで、異変に気付けやすいからです。
使用技術 javascript(next.js),typescript,tailwindcss, prisma, firebase, App-Router
こだわり
gemini-api を使用していますので質問などはAIが答えてくれます。
import React, { useState, useEffect } from 'react';
import { HashRouter as Router, Routes, Route, Link, useNavigate, useParams } from 'react-router-dom';
import {
Plus,
Home,
Settings,
Heart,
Activity,
Camera,
ChevronRight,
MessageSquare,
Weight,
Calendar,
Trash2,
Sparkles
} from 'lucide-react';
import { Cat, DailyLog } from './types';
import Dashboard from './pages/Dashboard';
import CatProfile from './pages/CatProfile';
import AddCat from './pages/AddCat';
import AIAssistant from './pages/AIAssistant';
const App: React.FC = () => {
const [cats, setCats] = useState(() => {
const saved = localStorage.getItem('catcare_cats');
return saved ? JSON.parse(saved) : [];
});
useEffect(() => {
localStorage.setItem('catcare_cats', JSON.stringify(cats));
}, [cats]);
const addCat = (newCat: Cat) => {
setCats(prev => [...prev, newCat]);
};
const updateCat = (updatedCat: Cat) => {
setCats(prev => prev.map(c => c.id === updatedCat.id ? updatedCat : c));
};
const deleteCat = (id: string) => {
setCats(prev => prev.filter(c => c.id !== id));
};
return (
{/* Sidebar for Desktop */}
<nav className="flex-1 space-y-2">
<NavLink to="/" icon={<Home size={20} />} label="ホーム" />
<NavLink to="/add" icon={<Plus size={20} />} label="猫を追加" />
<NavLink to="/ai-assistant" icon={<MessageSquare size={20} />} label="AI相談室" />
</nav>
<div className="pt-6 border-t border-slate-100">
<h3 className="text-xs font-semibold text-slate-400 uppercase tracking-wider mb-4">マイキャット</h3>
<div className="space-y-2 max-h-48 overflow-y-auto">
{cats.map(cat => (
<Link
key={cat.id}
to={`/cat/${cat.id}`}
className="flex items-center gap-3 p-2 rounded-lg hover:bg-slate-100 transition-colors group"
>
<img src={cat.photoUrl} alt={cat.name} className="w-8 h-8 rounded-full object-cover" />
<span className="text-sm font-medium text-slate-700 group-hover:text-orange-600 transition-colors">{cat.name}</span>
</Link>
))}
</div>
</div>
</aside>
{/* Mobile Navigation */}
<nav className="md:hidden fixed bottom-0 left-0 right-0 bg-white border-t border-slate-200 flex justify-around p-3 z-50">
<Link to="/" className="flex flex-col items-center p-2 text-slate-600">
<Home size={24} />
<span className="text-[10px] mt-1">ホーム</span>
</Link>
<Link to="/ai-assistant" className="flex flex-col items-center p-2 text-slate-600">
<MessageSquare size={24} />
<span className="text-[10px] mt-1">AI相談</span>
</Link>
<Link to="/add" className="flex flex-col items-center p-2 text-orange-500">
<div className="bg-orange-100 p-2 rounded-full -mt-6 border-4 border-white">
<Plus size={24} />
</div>
<span className="text-[10px] mt-1">追加</span>
</Link>
<div className="flex flex-col items-center p-2 text-slate-600">
<Heart size={24} />
<span className="text-[10px] mt-1">健康</span>
</div>
</nav>
{/* Main Content */}
<main className="flex-1 pb-24 md:pb-0 overflow-x-hidden">
<Routes>
<Route path="/" element={<Dashboard cats={cats} />} />
<Route path="/add" element={<AddCat onAdd={addCat} />} />
<Route path="/cat/:id" element={<CatProfile cats={cats} onUpdate={updateCat} onDelete={deleteCat} />} />
<Route path="/ai-assistant" element={<AIAssistant cats={cats} />} />
</Routes>
</main>
</div>
</Router>
);
};
const NavLink: React.FC<{ to: string, icon: React.ReactNode, label: string }> = ({ to, icon, label }) => (
{icon} {label} );export default App;