// DEPLOY_CONFIG: {"cron": [{"name": "weekly_water_change_reminder", "schedule": "0 9 * * 1", "action": "event", "config": {"event_type": "maintenance.weekly_water_change_reminder"}}, {"name": "monthly_filter_clean_reminder", "schedule": "0 9 1 * *", "action": "event", "config": {"event_type": "maintenance.monthly_filter_clean_reminder"}}], "triggers": [{"name": "water_parameter_danger_zone_alert", "on": "collection.add", "collection": "water_parameters", "actions": [{"type": "notification", "title": "Water parameter danger zone detected", "body": "A water parameter has entered a danger zone. Please review immediately."}, {"type": "email", "to": "alerts@deplixo.com", "subject": "Urgent: Water parameter danger zone detected", "body": "A water parameter has entered a danger zone. Please review the latest water parameter reading immediately."}]}]} import { useState } from 'react'; import { useAuth, useCollection, capturePhoto } from '@deplixo/sdk'; import { Dashboard } from './components/Dashboard.jsx'; import { WaterTests } from './components/WaterTests.jsx'; import { WaterChanges } from './components/WaterChanges.jsx'; import { Equipment } from './components/Equipment.jsx'; function App() { const { user, loading, login, logout } = useAuth(); const [activeTab, setActiveTab] = useState('dashboard'); const [selectedTankId, setSelectedTankId] = useState(''); const [tankName, setTankName] = useState(''); const [capturingTankId, setCapturingTankId] = useState(''); const [photoNotes, setPhotoNotes] = useState(''); const [fishSpecies, setFishSpecies] = useState(''); const [fishCount, setFishCount] = useState(''); const [editingFishId, setEditingFishId] = useState(''); const [editingFishSpecies, setEditingFishSpecies] = useState(''); const [editingFishCount, setEditingFishCount] = useState(''); const { items: tanks = [], add: addTank, update: updateTank, loading: tanksLoading } = useCollection('tanks', { personal: true }); const { items: tests = [] } = useCollection('waterTests', { personal: true }); const { items: changes = [] } = useCollection('waterChanges', { personal: true }); const { items: equipment = [] } = useCollection('equipment', { personal: true }); const { items: photos = [], add: addPhoto, loading: photosLoading } = useCollection('photos', { personal: true }); const { items: fish = [], add: addFish, update: updateFish, remove: removeFish } = useCollection('fish', { personal: true }); const tabs = [ { id: 'dashboard', label: '๐Ÿ“Š Dashboard', icon: '๐Ÿ“Š' }, { id: 'tests', label: '๐Ÿงช Water Tests', icon: '๐Ÿงช' }, { id: 'changes', label: '๐Ÿ’ง Water Changes', icon: '๐Ÿ’ง' }, { id: 'equipment', label: '๐Ÿ”ง Equipment', icon: '๐Ÿ”ง' }, ]; const handleAddTank = async () => { const name = tankName.trim(); if (!name) return; const newTank = await addTank({ name, createdAt: new Date().toISOString(), isDefault: tanks.length === 0, }); if (newTank?.id) { setSelectedTankId(newTank.id); } setTankName(''); }; const handleSelectTank = async (tank) => { if (!tank?.id) return; setSelectedTankId(tank.id); if (tank?.isDefault) { return; } const defaultTank = tanks.find((item) => item.isDefault); if (defaultTank?.id && defaultTank.id !== tank.id) { await updateTank(defaultTank.id, { isDefault: false }); } }; const handleCaptureTankPhoto = async (tankId) => { if (!tankId) return; setCapturingTankId(tankId); try { const result = await capturePhoto({ facing: 'environment' }); if (result?.url) { await addPhoto({ tankId, url: result.url, notes: photoNotes.trim(), createdAt: new Date().toISOString(), }); setPhotoNotes(''); } } finally { setCapturingTankId(''); } }; const handleAddFish = async () => { const species = fishSpecies.trim(); const count = Number(fishCount); if (!effectiveTankId || !species || !Number.isFinite(count) || count < 0) return; await addFish({ tankId: effectiveTankId, species, count: Math.floor(count), createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }); setFishSpecies(''); setFishCount(''); }; const startEditFish = (item) => { setEditingFishId(item.id); setEditingFishSpecies(item.species || ''); setEditingFishCount(String(item.count ?? 0)); }; const cancelEditFish = () => { setEditingFishId(''); setEditingFishSpecies(''); setEditingFishCount(''); }; const handleSaveFish = async (fishId) => { const species = editingFishSpecies.trim(); const count = Number(editingFishCount); if (!fishId || !species || !Number.isFinite(count) || count < 0) return; await updateFish(fishId, { species, count: Math.floor(count), updatedAt: new Date().toISOString(), }); cancelEditFish(); }; const handleRemoveFish = async (fishId) => { if (!fishId) return; await removeFish(fishId); if (editingFishId === fishId) cancelEditFish(); }; if (loading) return
Signing in...
; if (!user) { return (

๐Ÿ  AquaTrack

Aquarium Maintenance Tracker

Sign in to manage your personal aquariums

Use Google sign-in to keep each aquarium and tank scoped to your account.

); } const activeTank = tanks.find((tank) => tank.id === selectedTankId) || tanks.find((tank) => tank.isDefault) || tanks[0]; const effectiveTankId = activeTank?.id || selectedTankId; const scopedTests = tests.filter((item) => !effectiveTankId || item.tankId === effectiveTankId); const scopedChanges = changes.filter((item) => !effectiveTankId || item.tankId === effectiveTankId); const scopedEquipment = equipment.filter((item) => !effectiveTankId || item.tankId === effectiveTankId); const scopedPhotos = photos.filter((item) => !effectiveTankId || item.tankId === effectiveTankId); const scopedFish = fish.filter((item) => !effectiveTankId || item.tankId === effectiveTankId); const tankGalleryPhotos = scopedPhotos.slice().sort((a, b) => new Date(b.createdAt || 0) - new Date(a.createdAt || 0)); const fishInventory = scopedFish.slice().sort((a, b) => String(a.species || '').localeCompare(String(b.species || ''))); const fishTotal = fishInventory.reduce((sum, item) => sum + (Number(item.count) || 0), 0); return (

๐Ÿ  AquaTrack

Aquarium Maintenance Tracker

Signed in as {user.name}

Your Tanks

Tank Name setTankName(e.target.value)} placeholder="Add a tank" />
{(tanksLoading ? [] : tanks).map((tank) => ( ))} {!tanksLoading && tanks.length === 0 && No tanks yet. Add your first tank to scope logs.}
Current tank: {activeTank?.name || 'All Tanks'}
{activeTab === 'dashboard' && } {activeTab === 'tests' && } {activeTab === 'changes' && } {activeTab === 'equipment' && }

Fish Inventory

{fishTotal} total fish
Species setFishSpecies(e.target.value)} placeholder="e.g. Neon Tetra" disabled={!effectiveTankId} />
Count setFishCount(e.target.value)} placeholder="0" disabled={!effectiveTankId} />
{!effectiveTankId && Select a tank to manage fish inventory.}
{fishInventory.length === 0 ? (
๐ŸŸ

No fish inventory for this tank yet.

Add species and counts to keep track of livestock per tank.
) : (
{fishInventory.map((item) => { const isEditing = editingFishId === item.id; return (
{isEditing ? ( <>
Species setEditingFishSpecies(e.target.value)} />
Count setEditingFishCount(e.target.value)} />
) : ( <>
{item.species} {item.count} {Number(item.count) === 1 ? 'fish' : 'fish'}
)}
); })}
)}

Tank Photos

Photo Notes