Add automatic lunch feature. Clean up some code.

This commit is contained in:
2025-10-23 15:34:09 -05:00
parent 40489be8e9
commit 7eb3a1dff0
7 changed files with 197 additions and 126 deletions

View File

@@ -1,6 +1,5 @@
'use client';
import Image from 'next/image';
import { type ChangeEvent, useRef, useState } from 'react';
import {
type Preloaded,
@@ -49,7 +48,7 @@ export const AvatarUpload = ({ preloadedUser }: AvatarUploadProps) => {
const inputRef = useRef<HTMLInputElement>(null);
const generateUploadUrl = useMutation(api.files.generateUploadUrl);
const updateUserImage = useMutation(api.auth.updateUserImage);
const updateUser = useMutation(api.auth.updateUser);
const currentImageUrl = useQuery(
api.files.getImageUrl,
@@ -98,7 +97,7 @@ export const AvatarUpload = ({ preloadedUser }: AvatarUploadProps) => {
storageId: Id<'_storage'>;
};
await updateUserImage({ storageId: uploadResponse.storageId });
await updateUser({ image: uploadResponse.storageId });
toast.success('Profile picture updated.');
handleReset();

View File

@@ -51,12 +51,7 @@ export const UserInfoForm = ({ preloadedUser }: UserInfoFormProps) => {
const user = usePreloadedQuery(preloadedUser);
const [loading, setLoading] = useState(false);
const updateUserName = useMutation(api.auth.updateUserName);
const updateUserEmail = useMutation(api.auth.updateUserEmail);
const updateUserLunchtime = useMutation(api.auth.updateUserLunchtime);
const updateUserAutomaticLunch = useMutation(
api.auth.updateUserAutomaticLunch,
);
const updateUser = useMutation(api.auth.updateUser);
const initialValues = useMemo<z.infer<typeof formSchema>>(
() => ({
@@ -74,22 +69,29 @@ export const UserInfoForm = ({ preloadedUser }: UserInfoFormProps) => {
});
const handleSubmit = async (values: z.infer<typeof formSchema>) => {
const ops: Promise<unknown>[] = [];
const name = values.name.trim();
const email = values.email.trim().toLowerCase();
const lunchTime = values.lunchTime.trim();
const automaticLunch = values.automaticLunch;
if (name !== (user?.name ?? '')) ops.push(updateUserName({ name }));
if (email !== (user?.email ?? '')) ops.push(updateUserEmail({ email }));
if (lunchTime !== (user?.lunchTime ?? ''))
ops.push(updateUserLunchtime({ lunchTime }));
if (automaticLunch !== user?.automaticLunch)
ops.push(updateUserAutomaticLunch({ automaticLunch }));
if (ops.length === 0) return;
const patch: Partial<{
name: string;
email: string;
lunchTime: string;
automaticLunch: boolean;
}> = {};
if (name !== (user?.name ?? '') && name !== undefined)
patch.name = name;
if (email !== (user?.email ?? '') && email !== undefined)
patch.email = email;
if (lunchTime !== (user?.lunchTime && '') && lunchTime !== undefined)
patch.lunchTime = lunchTime;
if (automaticLunch !== user?.automaticLunch && automaticLunch !== undefined)
patch.automaticLunch = automaticLunch;
if (Object.keys(patch).length === 0) return;
setLoading(true);
try {
await Promise.all(ops);
form.reset({ name, email, lunchTime });
await updateUser(patch);
form.reset(patch);
toast.success('Profile updated successfully.');
} catch (error) {
console.error(error);

View File

@@ -16,12 +16,19 @@ const nextOccurrenceMs = (hhmm: string, from = new Date()): number => {
export const LunchReminder = () => {
const setStatus = useMutation(api.statuses.createLunchStatus);
const timeoutRef = useRef<number | null>(null);
const user = useQuery(api.auth.getUser);
const user = useQuery(api.auth.getUser, {});
const lunchTime = user?.lunchTime ?? '';
const automaticLunch = user?.automaticLunch ?? false;
useEffect(() => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
if (!lunchTime || automaticLunch) {
return;
}
const schedule = () => {
if (!lunchTime) return;
const ms = nextOccurrenceMs(lunchTime);
console.log('Ms = ', ms);
if (timeoutRef.current) clearTimeout(timeoutRef.current);
@@ -44,7 +51,7 @@ export const LunchReminder = () => {
description: 'Would you like to set your status to "At lunch"?',
action: {
label: 'Set to lunch',
onClick: () => void setStatus(),
onClick: () => void setStatus({}),
},
cancel: {
label: 'Not now',
@@ -59,9 +66,11 @@ export const LunchReminder = () => {
schedule();
return () => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null
}
};
}, [lunchTime, setStatus]);
}, [automaticLunch, lunchTime, setStatus]);
return null;
};

View File

@@ -1,6 +1,5 @@
'use client';
import { permission } from 'process';
import { useEffect } from 'react';
import { toast } from 'sonner';