Initial commit

This commit is contained in:
kihong.kim
2026-01-24 19:41:19 +09:00
commit 807df3d678
90 changed files with 6411 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
const express = require("express");
const Announcement = require("../models/Announcement");
const router = express.Router();
router.get("/", async (req, res) => {
try {
const filter = {};
if (req.query.active === "true") {
filter.active = true;
}
const announcements = await Announcement.find(filter).sort({
priority: -1,
createdAt: -1,
});
res.json(announcements);
} catch (error) {
res.status(500).json({ message: "Failed to fetch announcements" });
}
});
router.post("/", async (req, res) => {
try {
const announcement = await Announcement.create(req.body);
res.status(201).json(announcement);
} catch (error) {
res.status(400).json({ message: "Failed to create announcement" });
}
});
router.get("/:id", async (req, res) => {
try {
const announcement = await Announcement.findById(req.params.id);
if (!announcement) {
return res.status(404).json({ message: "Announcement not found" });
}
res.json(announcement);
} catch (error) {
res.status(400).json({ message: "Failed to fetch announcement" });
}
});
router.put("/:id", async (req, res) => {
try {
const announcement = await Announcement.findByIdAndUpdate(req.params.id, req.body, {
new: true,
});
if (!announcement) {
return res.status(404).json({ message: "Announcement not found" });
}
res.json(announcement);
} catch (error) {
res.status(400).json({ message: "Failed to update announcement" });
}
});
router.delete("/:id", async (req, res) => {
try {
const announcement = await Announcement.findByIdAndDelete(req.params.id);
if (!announcement) {
return res.status(404).json({ message: "Announcement not found" });
}
res.json({ ok: true });
} catch (error) {
res.status(400).json({ message: "Failed to delete announcement" });
}
});
module.exports = router;

94
backend/routes/bible.js Normal file
View File

@@ -0,0 +1,94 @@
const express = require("express");
const BibleVerse = require("../models/BibleVerse");
const router = express.Router();
const pickRandomVerse = async (filter) => {
const results = await BibleVerse.aggregate([
{ $match: filter },
{ $sample: { size: 1 } },
]);
return results[0] || null;
};
router.get("/today", async (req, res) => {
try {
const targetDate = req.query.date || new Date().toISOString().slice(0, 10);
const datedVerse = await pickRandomVerse({
active: true,
date: targetDate,
});
if (datedVerse) {
return res.json(datedVerse);
}
const undatedVerse = await pickRandomVerse({
active: true,
$or: [{ date: { $exists: false } }, { date: null }, { date: "" }],
});
if (undatedVerse) {
return res.json(undatedVerse);
}
const anyVerse = await pickRandomVerse({ active: true });
if (!anyVerse) {
return res.status(404).json({ message: "No bible verses available" });
}
return res.json(anyVerse);
} catch (error) {
res.status(500).json({ message: "Failed to fetch bible verse" });
}
});
router.get("/verses", async (req, res) => {
try {
const filter = {};
if (req.query.active === "true") {
filter.active = true;
}
const verses = await BibleVerse.find(filter).sort({
date: -1,
createdAt: -1,
});
res.json(verses);
} catch (error) {
res.status(500).json({ message: "Failed to fetch bible verses" });
}
});
router.post("/verses", async (req, res) => {
try {
const verse = await BibleVerse.create(req.body);
res.status(201).json(verse);
} catch (error) {
res.status(400).json({ message: "Failed to create bible verse" });
}
});
router.put("/verses/:id", async (req, res) => {
try {
const verse = await BibleVerse.findByIdAndUpdate(req.params.id, req.body, {
new: true,
});
if (!verse) {
return res.status(404).json({ message: "Bible verse not found" });
}
res.json(verse);
} catch (error) {
res.status(400).json({ message: "Failed to update bible verse" });
}
});
router.delete("/verses/:id", async (req, res) => {
try {
const verse = await BibleVerse.findByIdAndDelete(req.params.id);
if (!verse) {
return res.status(404).json({ message: "Bible verse not found" });
}
res.json({ ok: true });
} catch (error) {
res.status(400).json({ message: "Failed to delete bible verse" });
}
});
module.exports = router;

62
backend/routes/family.js Normal file
View File

@@ -0,0 +1,62 @@
const express = require("express");
const FamilyMember = require("../models/FamilyMember");
const router = express.Router();
router.get("/", async (req, res) => {
try {
const members = await FamilyMember.find().sort({ order: 1, createdAt: 1 });
res.json(members);
} catch (error) {
res.status(500).json({ message: "Failed to fetch family members" });
}
});
router.post("/", async (req, res) => {
try {
const member = await FamilyMember.create(req.body);
res.status(201).json(member);
} catch (error) {
res.status(400).json({ message: "Failed to create family member" });
}
});
router.get("/:id", async (req, res) => {
try {
const member = await FamilyMember.findById(req.params.id);
if (!member) {
return res.status(404).json({ message: "Family member not found" });
}
res.json(member);
} catch (error) {
res.status(400).json({ message: "Failed to fetch family member" });
}
});
router.put("/:id", async (req, res) => {
try {
const member = await FamilyMember.findByIdAndUpdate(req.params.id, req.body, {
new: true,
});
if (!member) {
return res.status(404).json({ message: "Family member not found" });
}
res.json(member);
} catch (error) {
res.status(400).json({ message: "Failed to update family member" });
}
});
router.delete("/:id", async (req, res) => {
try {
const member = await FamilyMember.findByIdAndDelete(req.params.id);
if (!member) {
return res.status(404).json({ message: "Family member not found" });
}
res.json({ ok: true });
} catch (error) {
res.status(400).json({ message: "Failed to delete family member" });
}
});
module.exports = router;

40
backend/routes/photos.js Normal file
View File

@@ -0,0 +1,40 @@
const express = require("express");
const Photo = require("../models/Photo");
const router = express.Router();
router.get("/", async (req, res) => {
try {
const filter = {};
if (req.query.active === "true") {
filter.active = true;
}
const photos = await Photo.find(filter).sort({ createdAt: -1 });
res.json(photos);
} catch (error) {
res.status(500).json({ message: "Failed to fetch photos" });
}
});
router.post("/", async (req, res) => {
try {
const photo = await Photo.create(req.body);
res.status(201).json(photo);
} catch (error) {
res.status(400).json({ message: "Failed to create photo" });
}
});
router.delete("/:id", async (req, res) => {
try {
const photo = await Photo.findByIdAndDelete(req.params.id);
if (!photo) {
return res.status(404).json({ message: "Photo not found" });
}
res.json({ ok: true });
} catch (error) {
res.status(400).json({ message: "Failed to delete photo" });
}
});
module.exports = router;

115
backend/routes/schedules.js Normal file
View File

@@ -0,0 +1,115 @@
const express = require("express");
const Schedule = require("../models/Schedule");
const router = express.Router();
const startOfWeek = (date = new Date()) => {
const copy = new Date(date);
const day = copy.getDay();
const diff = day === 0 ? -6 : 1 - day;
copy.setDate(copy.getDate() + diff);
copy.setHours(0, 0, 0, 0);
return copy;
};
const endOfWeek = (date = new Date()) => {
const start = startOfWeek(date);
const end = new Date(start);
end.setDate(end.getDate() + 6);
end.setHours(23, 59, 59, 999);
return end;
};
const startOfMonth = (date = new Date()) => {
return new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0, 0);
};
const endOfMonth = (date = new Date()) => {
return new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59, 999);
};
router.get("/", async (req, res) => {
try {
const schedules = await Schedule.find().sort({ startDate: 1 });
res.json(schedules);
} catch (error) {
res.status(500).json({ message: "Failed to fetch schedules" });
}
});
router.get("/week", async (req, res) => {
try {
const start = startOfWeek();
const end = endOfWeek();
const schedules = await Schedule.find({
startDate: { $lte: end },
endDate: { $gte: start },
}).sort({ startDate: 1 });
res.json(schedules);
} catch (error) {
res.status(500).json({ message: "Failed to fetch weekly schedules" });
}
});
router.get("/month", async (req, res) => {
try {
const start = startOfMonth();
const end = endOfMonth();
const schedules = await Schedule.find({
startDate: { $lte: end },
endDate: { $gte: start },
}).sort({ startDate: 1 });
res.json(schedules);
} catch (error) {
res.status(500).json({ message: "Failed to fetch monthly schedules" });
}
});
router.post("/", async (req, res) => {
try {
const schedule = await Schedule.create(req.body);
res.status(201).json(schedule);
} catch (error) {
res.status(400).json({ message: "Failed to create schedule" });
}
});
router.get("/:id", async (req, res) => {
try {
const schedule = await Schedule.findById(req.params.id);
if (!schedule) {
return res.status(404).json({ message: "Schedule not found" });
}
res.json(schedule);
} catch (error) {
res.status(400).json({ message: "Failed to fetch schedule" });
}
});
router.put("/:id", async (req, res) => {
try {
const schedule = await Schedule.findByIdAndUpdate(req.params.id, req.body, {
new: true,
});
if (!schedule) {
return res.status(404).json({ message: "Schedule not found" });
}
res.json(schedule);
} catch (error) {
res.status(400).json({ message: "Failed to update schedule" });
}
});
router.delete("/:id", async (req, res) => {
try {
const schedule = await Schedule.findByIdAndDelete(req.params.id);
if (!schedule) {
return res.status(404).json({ message: "Schedule not found" });
}
res.json({ ok: true });
} catch (error) {
res.status(400).json({ message: "Failed to delete schedule" });
}
});
module.exports = router;

81
backend/routes/todos.js Normal file
View File

@@ -0,0 +1,81 @@
const express = require("express");
const Todo = require("../models/Todo");
const router = express.Router();
const getDayRange = (date = new Date()) => {
const start = new Date(date);
start.setHours(0, 0, 0, 0);
const end = new Date(date);
end.setHours(23, 59, 59, 999);
return { start, end };
};
router.get("/", async (req, res) => {
try {
const todos = await Todo.find().sort({ dueDate: 1, createdAt: -1 });
res.json(todos);
} catch (error) {
res.status(500).json({ message: "Failed to fetch todos" });
}
});
router.get("/today", async (req, res) => {
try {
const { start, end } = getDayRange();
const todos = await Todo.find({ dueDate: { $gte: start, $lte: end } }).sort({
dueDate: 1,
createdAt: -1,
});
res.json(todos);
} catch (error) {
res.status(500).json({ message: "Failed to fetch today todos" });
}
});
router.post("/", async (req, res) => {
try {
const todo = await Todo.create(req.body);
res.status(201).json(todo);
} catch (error) {
res.status(400).json({ message: "Failed to create todo" });
}
});
router.get("/:id", async (req, res) => {
try {
const todo = await Todo.findById(req.params.id);
if (!todo) {
return res.status(404).json({ message: "Todo not found" });
}
res.json(todo);
} catch (error) {
res.status(400).json({ message: "Failed to fetch todo" });
}
});
router.put("/:id", async (req, res) => {
try {
const todo = await Todo.findByIdAndUpdate(req.params.id, req.body, { new: true });
if (!todo) {
return res.status(404).json({ message: "Todo not found" });
}
res.json(todo);
} catch (error) {
res.status(400).json({ message: "Failed to update todo" });
}
});
router.delete("/:id", async (req, res) => {
try {
const todo = await Todo.findByIdAndDelete(req.params.id);
if (!todo) {
return res.status(404).json({ message: "Todo not found" });
}
res.json({ ok: true });
} catch (error) {
res.status(400).json({ message: "Failed to delete todo" });
}
});
module.exports = router;

35
backend/routes/weather.js Normal file
View File

@@ -0,0 +1,35 @@
const express = require("express");
const axios = require("axios");
const config = require("../config/api");
const router = express.Router();
router.get("/", async (req, res) => {
try {
const { apiKey, baseUrl, city, units, language } = config.weather;
if (!apiKey) {
return res.status(400).json({ message: "OPENWEATHER_API_KEY is not set" });
}
const { q, lat, lon } = req.query;
const params = {
appid: apiKey,
units,
lang: language,
};
if (lat && lon) {
params.lat = lat;
params.lon = lon;
} else {
params.q = q || city;
}
const response = await axios.get(`${baseUrl}/weather`, { params });
res.json(response.data);
} catch (error) {
res.status(500).json({ message: "Failed to fetch weather" });
}
});
module.exports = router;