diff --git a/backend/routes/forum.js b/backend/routes/forum.js index ac75b73..51ea2a4 100644 --- a/backend/routes/forum.js +++ b/backend/routes/forum.js @@ -395,7 +395,21 @@ router.post('/posts', authenticateToken, uploadForumPostImages, async (req, res) attributes: ['itemRequestNotificationRadius'] }); - const userPreferredRadius = userProfile?.itemRequestNotificationRadius || 10; + const userPreferredRadius = userProfile?.itemRequestNotificationRadius; + + // Skip if user has disabled notifications (null) + if (userPreferredRadius === null || userPreferredRadius === undefined) { + logger.info("User has disabled item request notifications", { + postId: post.id, + userId: user.id, + userDistance: user.distance + }); + usersSkipped++; + continue; + } + + // Default to 10 miles if somehow not set + const effectiveRadius = userPreferredRadius || 10; logger.info("Checking user notification eligibility", { postId: post.id, @@ -404,12 +418,12 @@ router.post('/posts', authenticateToken, uploadForumPostImages, async (req, res) userCoordinates: { lat: user.latitude, lng: user.longitude }, postCoordinates: { lat: latitude, lng: longitude }, userDistance: user.distance, - userPreferredRadius, - willNotify: parseFloat(user.distance) <= userPreferredRadius + userPreferredRadius: effectiveRadius, + willNotify: parseFloat(user.distance) <= effectiveRadius }); // Only notify if within user's preferred radius - if (parseFloat(user.distance) <= userPreferredRadius) { + if (parseFloat(user.distance) <= effectiveRadius) { try { await emailServices.forum.sendItemRequestNotification( user, diff --git a/frontend/src/pages/Profile.tsx b/frontend/src/pages/Profile.tsx index cb42916..1101279 100644 --- a/frontend/src/pages/Profile.tsx +++ b/frontend/src/pages/Profile.tsx @@ -14,7 +14,10 @@ import { } from "../services/geocodingService"; import AddressAutocomplete from "../components/AddressAutocomplete"; import { PlaceDetails } from "../services/placesService"; -import { useAddressAutocomplete, usStates } from "../hooks/useAddressAutocomplete"; +import { + useAddressAutocomplete, + usStates, +} from "../hooks/useAddressAutocomplete"; const Profile: React.FC = () => { const { user, updateUser, logout } = useAuth(); @@ -25,7 +28,20 @@ const Profile: React.FC = () => { const [success, setSuccess] = useState(null); const [activeSection, setActiveSection] = useState("overview"); const [profileData, setProfileData] = useState(null); - const [formData, setFormData] = useState({ + const [formData, setFormData] = useState<{ + firstName: string; + lastName: string; + email: string; + phone: string; + address1: string; + address2: string; + city: string; + state: string; + zipCode: string; + country: string; + profileImage: string; + itemRequestNotificationRadius: number | null; + }>({ firstName: "", lastName: "", email: "", @@ -141,7 +157,8 @@ const Profile: React.FC = () => { zipCode: response.data.zipCode || "", country: response.data.country || "", profileImage: response.data.profileImage || "", - itemRequestNotificationRadius: response.data.itemRequestNotificationRadius || 10, + itemRequestNotificationRadius: + response.data.itemRequestNotificationRadius || 10, }); if (response.data.profileImage) { setImagePreview(getImageUrl(response.data.profileImage)); @@ -264,7 +281,9 @@ const Profile: React.FC = () => { }; const handleChange = ( - e: React.ChangeEvent + e: React.ChangeEvent< + HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement + > ) => { const { name, value } = e.target; setFormData((prev) => ({ ...prev, [name]: value })); @@ -361,7 +380,8 @@ const Profile: React.FC = () => { zipCode: profileData.zipCode || "", country: profileData.country || "", profileImage: profileData.profileImage || "", - itemRequestNotificationRadius: profileData.itemRequestNotificationRadius || 10, + itemRequestNotificationRadius: + profileData.itemRequestNotificationRadius || 10, }); setImagePreview( profileData.profileImage ? getImageUrl(profileData.profileImage) : null @@ -415,7 +435,10 @@ const Profile: React.FC = () => { setSuccess("Notification preferences saved successfully"); setTimeout(() => setSuccess(null), 3000); } catch (err: any) { - console.error("Notification preferences update error:", err.response?.data); + console.error( + "Notification preferences update error:", + err.response?.data + ); const errorMessage = err.response?.data?.error || err.response?.data?.message || @@ -428,7 +451,10 @@ const Profile: React.FC = () => { e: React.ChangeEvent ) => { const { value } = e.target; - setFormData((prev) => ({ ...prev, itemRequestNotificationRadius: parseInt(value) })); + setFormData((prev) => ({ + ...prev, + itemRequestNotificationRadius: parseInt(value), + })); setError(null); try { @@ -438,7 +464,10 @@ const Profile: React.FC = () => { setProfileData(response.data); updateUser(response.data); } catch (err: any) { - console.error("Notification preferences update error:", err.response?.data); + console.error( + "Notification preferences update error:", + err.response?.data + ); const errorMessage = err.response?.data?.error || err.response?.data?.message || @@ -560,8 +589,8 @@ const Profile: React.FC = () => { ...addressFormData, ...(coordinates && { latitude: coordinates.latitude, - longitude: coordinates.longitude - }) + longitude: coordinates.longitude, + }), }; try { @@ -614,17 +643,20 @@ const Profile: React.FC = () => { const { parsePlace } = useAddressAutocomplete(); // Handle place selection from autocomplete - const handlePlaceSelect = useCallback((place: PlaceDetails) => { - const parsedAddress = parsePlace(place); - if (parsedAddress) { - setAddressFormData((prev) => ({ - ...prev, - ...parsedAddress, - })); - setAddressGeocodeSuccess(true); - setTimeout(() => setAddressGeocodeSuccess(false), 3000); - } - }, [parsePlace]); + const handlePlaceSelect = useCallback( + (place: PlaceDetails) => { + const parsedAddress = parsePlace(place); + if (parsedAddress) { + setAddressFormData((prev) => ({ + ...prev, + ...parsedAddress, + })); + setAddressGeocodeSuccess(true); + setTimeout(() => setAddressGeocodeSuccess(false), 3000); + } + }, + [parsePlace] + ); if (loading) { return ( @@ -781,335 +813,344 @@ const Profile: React.FC = () => { type="button" className="btn btn-link text-primary p-0 ms-2" onClick={() => setShowPersonalInfo(!showPersonalInfo)} - style={{ textDecoration: 'none' }} + style={{ textDecoration: "none" }} > - + {showPersonalInfo && (
-
-
-