added family auth context to sleep logs

This commit is contained in:
John Overton
2025-06-09 11:39:48 -05:00
parent 4e45ea8aff
commit e310d947ae
3 changed files with 42 additions and 36 deletions
+38 -23
View File
@@ -3,19 +3,28 @@ import prisma from '../db';
import { ApiResponse, SleepLogCreate, SleepLogResponse } from '../types';
import { withAuthContext, AuthResult } from '../utils/auth';
import { toUTC, formatForResponse, calculateDurationMinutes } from '../utils/timezone';
import { getFamilyIdFromRequest } from '../utils/family';
async function handlePost(req: NextRequest, authContext: AuthResult) {
try {
const { familyId: userFamilyId, caretakerId } = authContext;
if (!userFamilyId) {
return NextResponse.json<ApiResponse<null>>({ success: false, error: 'User is not associated with a family.' }, { status: 403 });
}
const body: SleepLogCreate = await req.json();
const baby = await prisma.baby.findFirst({
where: { id: body.babyId, familyId: userFamilyId },
});
if (!baby) {
return NextResponse.json<ApiResponse<null>>({ success: false, error: 'Baby not found in this family.' }, { status: 404 });
}
// Convert times to UTC for storage
const startTimeUTC = toUTC(body.startTime);
const endTimeUTC = body.endTime ? toUTC(body.endTime) : null;
// Get family ID from request (body, query params, or URL slug)
const familyId = await getFamilyIdFromRequest(req, body);
// Calculate duration if both start and end times are present
const duration = endTimeUTC ? calculateDurationMinutes(startTimeUTC, endTimeUTC) : undefined;
@@ -25,8 +34,8 @@ async function handlePost(req: NextRequest, authContext: AuthResult) {
startTime: startTimeUTC,
...(endTimeUTC && { endTime: endTimeUTC }),
duration,
caretakerId: authContext.caretakerId,
...(familyId && { familyId }), // Include family ID if available
caretakerId: caretakerId,
familyId: userFamilyId,
},
});
@@ -58,6 +67,11 @@ async function handlePost(req: NextRequest, authContext: AuthResult) {
async function handlePut(req: NextRequest, authContext: AuthResult) {
try {
const { familyId: userFamilyId } = authContext;
if (!userFamilyId) {
return NextResponse.json<ApiResponse<null>>({ success: false, error: 'User is not associated with a family.' }, { status: 403 });
}
const { searchParams } = new URL(req.url);
const id = searchParams.get('id');
const body: Partial<SleepLogCreate> = await req.json();
@@ -72,18 +86,15 @@ async function handlePut(req: NextRequest, authContext: AuthResult) {
);
}
// Get family ID from request (query params or URL slug)
const familyId = await getFamilyIdFromRequest(req);
const existingSleepLog = await prisma.sleepLog.findFirst({
where: { id, ...(familyId && { familyId }) },
where: { id, familyId: userFamilyId },
});
if (!existingSleepLog) {
return NextResponse.json<ApiResponse<SleepLogResponse>>(
{
success: false,
error: 'Sleep log not found',
error: 'Sleep log not found or access denied',
},
{ status: 404 }
);
@@ -136,16 +147,19 @@ async function handlePut(req: NextRequest, authContext: AuthResult) {
async function handleGet(req: NextRequest, authContext: AuthResult) {
try {
const { familyId: userFamilyId } = authContext;
if (!userFamilyId) {
return NextResponse.json<ApiResponse<null>>({ success: false, error: 'User is not associated with a family.' }, { status: 403 });
}
const { searchParams } = new URL(req.url);
const id = searchParams.get('id');
const babyId = searchParams.get('babyId');
const startDate = searchParams.get('startDate');
const endDate = searchParams.get('endDate');
// Get family ID from request (query params or URL slug)
const familyId = await getFamilyIdFromRequest(req);
const queryParams = {
const queryParams: any = {
familyId: userFamilyId,
...(babyId && { babyId }),
...(startDate && endDate && {
startTime: {
@@ -153,14 +167,13 @@ async function handleGet(req: NextRequest, authContext: AuthResult) {
lte: toUTC(endDate),
},
}),
...(familyId && { familyId }), // Filter by family ID if available
};
if (id) {
const sleepLog = await prisma.sleepLog.findFirst({
where: {
id,
...(familyId && { familyId }), // Filter by family ID if available
familyId: userFamilyId,
},
});
@@ -168,7 +181,7 @@ async function handleGet(req: NextRequest, authContext: AuthResult) {
return NextResponse.json<ApiResponse<SleepLogResponse>>(
{
success: false,
error: 'Sleep log not found',
error: 'Sleep log not found or access denied',
},
{ status: 404 }
);
@@ -225,6 +238,11 @@ async function handleGet(req: NextRequest, authContext: AuthResult) {
async function handleDelete(req: NextRequest, authContext: AuthResult) {
try {
const { familyId: userFamilyId } = authContext;
if (!userFamilyId) {
return NextResponse.json<ApiResponse<null>>({ success: false, error: 'User is not associated with a family.' }, { status: 403 });
}
const { searchParams } = new URL(req.url);
const id = searchParams.get('id');
@@ -238,18 +256,15 @@ async function handleDelete(req: NextRequest, authContext: AuthResult) {
);
}
// Get family ID from request (query params or URL slug)
const familyId = await getFamilyIdFromRequest(req);
const existingSleepLog = await prisma.sleepLog.findFirst({
where: { id, ...(familyId && { familyId }) },
where: { id, familyId: userFamilyId },
});
if (!existingSleepLog) {
return NextResponse.json<ApiResponse<void>>(
{
success: false,
error: 'Sleep log not found',
error: 'Sleep log not found or access denied',
},
{ status: 404 }
);
@@ -116,7 +116,7 @@ This checklist tracks the progress of refactoring each component and its associa
- [x] **Pump Log**
- Form: `src/components/forms/PumpForm/`
- API: `app/api/pump-log/`
- [ ] **Sleep Log**
- [x] **Sleep Log**
- Form: `src/components/forms/SleepForm/`
- API: `app/api/sleep-log/`
+3 -12
View File
@@ -20,7 +20,6 @@ import {
FormPageFooter
} from '@/src/components/ui/form-page';
import { useTimezone } from '@/app/context/timezone';
import { useFamily } from '@/src/context/family';
interface SleepFormProps {
isOpen: boolean;
@@ -31,7 +30,6 @@ interface SleepFormProps {
initialTime: string;
activity?: SleepLogResponse;
onSuccess?: () => void;
familyId?: string; // Add familyId prop for multi-family support
}
export default function SleepForm({
@@ -43,10 +41,8 @@ export default function SleepForm({
initialTime,
activity,
onSuccess,
familyId,
}: SleepFormProps) {
const { formatDate, calculateDurationMinutes, toUTCString } = useTimezone();
const { family } = useFamily();
const [startDateTime, setStartDateTime] = useState<Date>(() => {
try {
// Try to parse the initialTime
@@ -106,8 +102,7 @@ export default function SleepForm({
try {
// Get auth token from localStorage
const authToken = localStorage.getItem('authToken');
const familyIdToUse = familyId || family?.id;
const url = `/api/sleep-log?babyId=${babyId}${familyIdToUse ? `&familyId=${familyIdToUse}` : ''}`;
const url = `/api/sleep-log?babyId=${babyId}`;
const response = await fetch(url, {
headers: {
@@ -198,7 +193,7 @@ export default function SleepForm({
quality: '' as SleepQuality | '',
});
}
}, [isOpen, initialTime, isSleeping, babyId, familyId, activity?.id, isInitialized, family]);
}, [isOpen, initialTime, isSleeping, babyId, activity?.id, isInitialized]);
// Handle date/time changes
const handleStartDateTimeChange = (date: Date) => {
@@ -254,7 +249,6 @@ export default function SleepForm({
type: formData.type,
location: formData.location || null,
quality: formData.quality || null,
familyId: familyId || family?.id || undefined, // Include familyId in the payload
};
// Get auth token from localStorage
@@ -272,8 +266,7 @@ export default function SleepForm({
// Ending sleep - update existing record
// Get auth token from localStorage
const authToken = localStorage.getItem('authToken');
const familyIdToUse = familyId || family?.id;
const url = `/api/sleep-log?babyId=${babyId}${familyIdToUse ? `&familyId=${familyIdToUse}` : ''}`;
const url = `/api/sleep-log?babyId=${babyId}`;
const sleepResponse = await fetch(url, {
headers: {
@@ -297,7 +290,6 @@ export default function SleepForm({
endTime: utcEndTime,
duration,
quality: formData.quality || null,
familyId: familyId || family?.id || undefined, // Include familyId in the payload
}),
});
} else {
@@ -310,7 +302,6 @@ export default function SleepForm({
type: formData.type,
location: formData.location || null,
quality: null,
familyId: familyId || family?.id || undefined, // Include familyId in the payload
};
// Get auth token from localStorage