From 3d76ccf3bef2b8d247efd665b3eaef0a9b02cc79 Mon Sep 17 00:00:00 2001 From: jason Date: Sun, 8 Mar 2026 22:46:21 -0500 Subject: [PATCH] Add breeding/heat cycle API routes --- server/routes/breeding.js | 133 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 server/routes/breeding.js diff --git a/server/routes/breeding.js b/server/routes/breeding.js new file mode 100644 index 0000000..0bec351 --- /dev/null +++ b/server/routes/breeding.js @@ -0,0 +1,133 @@ +const express = require('express'); +const router = express.Router(); +const { getDatabase } = require('../db/init'); + +// GET all heat cycles for a dog +router.get('/heat-cycles/dog/:dogId', (req, res) => { + try { + const db = getDatabase(); + const cycles = db.prepare(` + SELECT * FROM heat_cycles + WHERE dog_id = ? + ORDER BY start_date DESC + `).all(req.params.dogId); + + res.json(cycles); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +// GET all active heat cycles +router.get('/heat-cycles/active', (req, res) => { + try { + const db = getDatabase(); + const cycles = db.prepare(` + SELECT hc.*, d.name as dog_name, d.registration_number + FROM heat_cycles hc + JOIN dogs d ON hc.dog_id = d.id + WHERE hc.end_date IS NULL OR hc.end_date >= date('now', '-30 days') + ORDER BY hc.start_date DESC + `).all(); + + res.json(cycles); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +// POST create heat cycle +router.post('/heat-cycles', (req, res) => { + try { + const { dog_id, start_date, end_date, progesterone_peak_date, breeding_date, breeding_successful, notes } = req.body; + + if (!dog_id || !start_date) { + return res.status(400).json({ error: 'Dog ID and start date are required' }); + } + + const db = getDatabase(); + + // Verify dog is female + const dog = db.prepare('SELECT sex FROM dogs WHERE id = ?').get(dog_id); + if (!dog || dog.sex !== 'female') { + return res.status(400).json({ error: 'Dog must be female' }); + } + + const result = db.prepare(` + INSERT INTO heat_cycles (dog_id, start_date, end_date, progesterone_peak_date, breeding_date, breeding_successful, notes) + VALUES (?, ?, ?, ?, ?, ?, ?) + `).run(dog_id, start_date, end_date, progesterone_peak_date, breeding_date, breeding_successful || 0, notes); + + const cycle = db.prepare('SELECT * FROM heat_cycles WHERE id = ?').get(result.lastInsertRowid); + + res.status(201).json(cycle); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +// PUT update heat cycle +router.put('/heat-cycles/:id', (req, res) => { + try { + const { start_date, end_date, progesterone_peak_date, breeding_date, breeding_successful, notes } = req.body; + + const db = getDatabase(); + db.prepare(` + UPDATE heat_cycles + SET start_date = ?, end_date = ?, progesterone_peak_date = ?, + breeding_date = ?, breeding_successful = ?, notes = ? + WHERE id = ? + `).run(start_date, end_date, progesterone_peak_date, breeding_date, breeding_successful, notes, req.params.id); + + const cycle = db.prepare('SELECT * FROM heat_cycles WHERE id = ?').get(req.params.id); + res.json(cycle); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +// DELETE heat cycle +router.delete('/heat-cycles/:id', (req, res) => { + try { + const db = getDatabase(); + db.prepare('DELETE FROM heat_cycles WHERE id = ?').run(req.params.id); + res.json({ message: 'Heat cycle deleted successfully' }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +// GET calculate expected whelping date +router.get('/whelping-calculator', (req, res) => { + try { + const { breeding_date } = req.query; + + if (!breeding_date) { + return res.status(400).json({ error: 'Breeding date is required' }); + } + + const breedDate = new Date(breeding_date); + + // Average gestation: 63 days, range 58-68 days + const expectedDate = new Date(breedDate); + expectedDate.setDate(expectedDate.getDate() + 63); + + const earliestDate = new Date(breedDate); + earliestDate.setDate(earliestDate.getDate() + 58); + + const latestDate = new Date(breedDate); + latestDate.setDate(latestDate.getDate() + 68); + + res.json({ + breeding_date: breeding_date, + expected_whelping_date: expectedDate.toISOString().split('T')[0], + earliest_date: earliestDate.toISOString().split('T')[0], + latest_date: latestDate.toISOString().split('T')[0], + gestation_days: 63 + }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +module.exports = router; \ No newline at end of file