Skip to content

Commit 7c27d1b

Browse files
Code optimization and manual testing
1 parent a8661d5 commit 7c27d1b

18 files changed

Lines changed: 186 additions & 149 deletions

File tree

client/app/(auth)/login/login.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,15 @@ export default function LoginPage() {
101101
disabled={false}
102102
/>
103103
</div>
104-
<div>
104+
<div>
105105
<button
106106
type="submit"
107107
disabled={isPending}
108108
className="w-full bg-green-600 mt-2 hover:bg-green-700 hover:cursor-pointer text-white py-2 px-4 rounded-lg transition"
109109
>
110110
{isPending ? "Logging in..." : "Login"}
111111
</button>
112-
</div>
112+
</div>
113113
</form>
114114
</div>
115115
</div>

client/app/(auth)/signup/signUp.tsx

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,31 +46,46 @@ export default function SignupForm() {
4646

4747
const { getCurrentLocation, fetchLocationName, isLoading,getLocationNameFromLatLng } = useLocation();
4848

49+
function setLatLng(data?: { lat?: any; lng?: any }) {
50+
if (!data) return;
51+
52+
const latNum = Number(data.lat);
53+
const lngNum = Number(data.lng);
54+
55+
if (!isNaN(latNum)) setValue("lat", latNum);
56+
if (!isNaN(lngNum)) setValue("lng", lngNum);
57+
}
58+
4959
const handleGetLocation = async () => {
5060
try {
51-
const { lat, lng } = await getCurrentLocation();
61+
const data= await getCurrentLocation();
5262
const location = await fetchLocationName(lat, lng);
53-
console.log(" lat, lng ", lat, lng )
54-
setValue("lat", lat);
55-
setValue("lng", lng);
63+
setLatLng(data);
5664
setValue("location", location || "Location found but could not get name");
5765
} catch (err: any) {
5866
setValue("location", err.message || "Failed to get location");
5967
}
6068
};
6169

6270
const {location,lat,lng} = watch();
63-
71+
const handleLocationChange = (location: string) => {
72+
if (location.length > 3 && !lng) {
73+
try {
74+
setTimeout( async () => {
75+
const data = await getLocationNameFromLatLng(location);
76+
setLatLng(data);
77+
},500)
78+
} catch (error) {
79+
console.error("Geocoding failed:", error);
80+
}
81+
}
82+
};
6483
useEffect(() => {
65-
async function getAddress() {
66-
if(location && !lat && !lng) {
67-
const data = await getLocationNameFromLatLng(location)
68-
setValue("lat", data?.lat);
69-
setValue("lng", data?.lng);
84+
if(location){
85+
console.log("locations")
86+
handleLocationChange(location);
7087
}
71-
}
72-
setTimeout(() => getAddress(),1000);
73-
}, [location])
88+
},[location]);
7489

7590
const { mutate, isPending, isSuccess, isError } = useMutation({
7691
mutationFn: signupUser,
@@ -86,10 +101,14 @@ export default function SignupForm() {
86101
},
87102
});
88103

89-
const onSubmit = (data: SignUpFormData) => {
90-
console.log(data,"data signup")
91-
mutate(data);
92-
};
104+
const onSubmit = async (data: SignUpFormData) => {
105+
try {
106+
mutate(data);
107+
} catch (error:any) {
108+
console.error("Form submission error:", error);
109+
setErrorMsg(error.message || "Failed to submit form");
110+
}
111+
};
93112

94113
return (
95114
<>

client/app/_lib/context/contextAPI.tsx

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,6 @@
11
'use client';
2+
import { SidebarContextType } from '@/app/type/type';
23
import { createContext, useContext, useEffect, useState } from 'react';
3-
4-
interface SidebarContextType {
5-
isCollapsed: boolean;
6-
toggleSidebar: () => void;
7-
isLogin: boolean;
8-
setIsLogin: React.Dispatch<React.SetStateAction<boolean>>;
9-
isSignUp: boolean;
10-
setIsSignUp: React.Dispatch<React.SetStateAction<boolean>>;
11-
isProfile: boolean;
12-
setIsProfile: React.Dispatch<React.SetStateAction<boolean>>;
13-
token: string;
14-
setTokenState: React.Dispatch<React.SetStateAction<string>>;
15-
logout: () => void;
16-
}
17-
184
const contextAPI = createContext<SidebarContextType>({
195
isCollapsed: false,
206
toggleSidebar: () => {},

client/app/_lib/review/review.tsx

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,7 @@ import { getUserProfile } from '../services/userService';
99
import { useQuery } from '@tanstack/react-query';
1010
import Loader from '@/app/components/specialized/Loader';
1111
import ErrorMessage from '@/app/components/specialized/ErrorMessage';
12-
13-
interface Review {
14-
id: string;
15-
rating: number;
16-
comment: string;
17-
createdAt: string;
18-
user:{
19-
email:string;
20-
name: string;
21-
}
22-
}
23-
24-
interface ReviewSectionProps {
25-
reviews: Review[];
26-
averageRating: number;
27-
featureId: string;
28-
token:string;
29-
onReviewSubmit: (rating: number, comment: string) => Promise<void>;
30-
onReviewRemove:(id:string) => Promise<void>,
31-
onReviewUpdate:(rating: number,editingReviewId:string, reviewText: string) => Promise<void>;
32-
}
33-
12+
import { ReviewSectionProps } from '@/app/type/type';
3413
export default function ReviewSection({
3514
reviews,
3615
averageRating,

client/app/_lib/services/reviewService.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ token
2626
};
2727

2828
export const removeReview =async ({reviewId,token}:{reviewId:string, token:string}) => {
29-
const res = await fetch(`${process.env.NEXT_PUBLIC_API_BASE}/api/deleteReviews`, {
29+
const res = await fetch(`${process.env.NEXT_PUBLIC_API_BASE}/deleteReviews`, {
3030
method: "DELETE",
3131
headers: {
3232
"Content-Type": "application/json",

client/app/components/Feature/Filter.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'use client'
2-
import { useState } from 'react'
2+
import { useEffect, useMemo, useState } from 'react'
33
import { Shapes, ChevronDown } from 'lucide-react'
44

55
export default function CategorySelect({
@@ -10,17 +10,30 @@ export default function CategorySelect({
1010
const [open, setOpen] = useState(false)
1111
const [selected, setSelected] = useState<string | null>(null)
1212

13-
const categories = ['museum', 'restaurant', 'theatre', 'artwork']
13+
const categories = useMemo(() => ['museum', 'restaurant', 'theatre', 'artwork'], []);
14+
15+
useEffect(() => {
16+
const handleClickOutside = (e: MouseEvent) => {
17+
if (!(e.target as HTMLElement).closest('#category-dropdown')) {
18+
setOpen(false);
19+
}
20+
};
21+
document.addEventListener('mousedown', handleClickOutside);
22+
return () => document.removeEventListener('mousedown', handleClickOutside);
23+
}, []);
1424

1525
const handleCategorySelect = (category: string) => {
1626
setSelected(() => category)
17-
setOpen(() => false)
27+
setOpen(() => false);
1828
if (onSelect) onSelect(category)
1929
}
2030

2131
return (
22-
<div className='relative'>
32+
<div className='relative' id="category-dropdown" role="listbox">
2333
<button
34+
aria-haspopup="listbox"
35+
aria-expanded={open}
36+
aria-label="Select category"
2437
onClick={() => setOpen(!open)}
2538
className='flex items-center gap-1 bg-white px-3 py-1.5 rounded-lg shadow hover:bg-gray-100 transition'
2639
>

client/app/components/Feature/SearchBar.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
'use client'
22

33
import { useState, useEffect } from 'react'
4-
import { CornerUpRight, Search, MapPin, X } from 'lucide-react'
4+
import { Search, MapPin, X } from 'lucide-react'
55
import type { Feature } from 'geojson'
6-
7-
interface SearchBarProps {
8-
geoData: any
9-
searchHanlde?: (key: string) => void
10-
handleRefresh?: () => void
11-
}
6+
import { SearchBarProps } from '@/app/type/type'
127

138
export default function SearchBar({
149
geoData,

client/app/components/common/Card.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,7 @@ import { useContextAPI } from '../../_lib/context/contextAPI';
88
import { findAllFavorites } from '../../_lib/services/favoriteService'
99
import Loader from '../../components/specialized/Loader'
1010
import ErrorMessage from '../../components/specialized/ErrorMessage';
11-
interface TextCardProps {
12-
id:string;
13-
title: string;
14-
description: string;
15-
rating?: number;
16-
reviews?: number;
17-
onView?: () => void;
18-
token:string;
19-
refetch?: () => void
20-
}
11+
import { TextCardProps } from '@/app/type/type';
2112

2213
const TextCard: React.FC<TextCardProps> = ({
2314
id,
@@ -50,7 +41,7 @@ const TextCard: React.FC<TextCardProps> = ({
5041
View
5142
</button>
5243
</Link>
53-
<FavoriteFunctionality id={id} token={token} onFavoriteChange={refetch}/>
44+
<FavoriteFunctionality id={id} onFavoriteChange={refetch}/>
5445
</div>
5546
</div>
5647
);

client/app/components/common/FavoriteFunctionality.tsx

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
11
import { useMutation, useQuery } from '@tanstack/react-query'
2-
import React from 'react'
2+
import { MouseEvent, useEffect, useState } from 'react'
33
import {
44
addFavorite,
55
findFavorite,
66
removeFavorite,
77
} from '../../_lib/services/favoriteService'
88
import { HeartMinus, HeartPlus } from 'lucide-react'
9-
10-
interface FavoriteFunctionalityProps {
11-
id: string
12-
token: string
13-
onFavoriteChange?: () => void // New callback prop
14-
}
9+
import { FavoriteFunctionalityProps } from '@/app/type/type'
10+
import { useContextAPI } from '@/app/_lib/context/contextAPI'
1511

1612
const FavoriteFunctionality = ({
1713
id,
18-
token,
1914
onFavoriteChange,
2015
}: FavoriteFunctionalityProps) => {
16+
const [token, setToken] = useState<string>('')
2117
const { data, refetch } = useQuery({
2218
queryKey: ['favorite', token, id],
2319
queryFn: findFavorite,
2420
enabled: !!token,
21+
staleTime: 1000,
2522
})
26-
console.log('token=>', token, 'id=>', id)
23+
24+
useEffect(() => {
25+
const token = localStorage.getItem('token')
26+
if (token) {
27+
setToken(token)
28+
refetch()
29+
}
30+
}, [token, refetch])
2731
const addFavoriteMutation = useMutation({
2832
mutationFn: addFavorite,
2933
onSuccess: () => {
@@ -41,37 +45,37 @@ const FavoriteFunctionality = ({
4145
})
4246

4347
const handleFavorite = (e: React.MouseEvent) => {
44-
e.preventDefault()
45-
e.stopPropagation()
4648
addFavoriteMutation.mutate({ featureId: id, token })
4749
}
4850

49-
const handleUnFavorite = (e: React.MouseEvent) => {
50-
e.preventDefault()
51-
e.stopPropagation()
51+
const handleUnFavorite = (e: MouseEvent) => {
5252
removeFavoriteMutation.mutate({ featureId: id, token })
5353
}
5454
return (
55-
<button
56-
className='flex gap-1 justify-center items-center ml-2 cursor-pointer'
57-
aria-label={
58-
data?.featureId ? 'Remove from favorites' : 'Add to favorites'
59-
}
60-
>
61-
<div className='hover: cursor-pointer'>
62-
{data?.featureId ? (
63-
<HeartMinus
64-
size={18}
65-
color='red'
66-
fill='red'
67-
onClick={handleUnFavorite}
68-
/>
69-
) : (
70-
<HeartPlus size={18} color='gray' onClick={handleFavorite} />
71-
)}
72-
</div>
73-
<span>{data?.count || 0}</span>
74-
</button>
55+
<>
56+
{token && (
57+
<button
58+
className='flex gap-1 justify-center items-center ml-2 cursor-pointer'
59+
aria-label={
60+
data?.featureId ? 'Remove from favorites' : 'Add to favorites'
61+
}
62+
>
63+
<div className='hover: cursor-pointer'>
64+
{data?.featureId ? (
65+
<HeartMinus
66+
size={18}
67+
color='red'
68+
fill='red'
69+
onClick={handleUnFavorite}
70+
/>
71+
) : (
72+
<HeartPlus size={18} color='gray' onClick={handleFavorite} />
73+
)}
74+
</div>
75+
<span>{data?.count || 0}</span>
76+
</button>
77+
)}
78+
</>
7579
)
7680
}
7781

client/app/components/common/GeoCard.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,10 @@
22
import React from 'react';
33
import Link from 'next/link';
44
import FavoriteFunctionality from './FavoriteFunctionality';
5+
import { PopupCardProps } from '@/app/type/type';
56

6-
interface PopupCardProps {
7-
id: string;
8-
name?: string;
9-
token: string;
10-
}
11-
12-
const GeoCard = ({ id, name, token }: PopupCardProps) => {
7+
const GeoCard = ({ id, name }: PopupCardProps) => {
138
const encodedId = encodeURIComponent(id);
14-
159
return (
1610
<div style={{
1711
width: 180,
@@ -30,7 +24,7 @@ const GeoCard = ({ id, name, token }: PopupCardProps) => {
3024
</div>
3125
</div>
3226
</Link>
33-
{id && token && <FavoriteFunctionality id={id} token={token}/>}
27+
{<FavoriteFunctionality id={id} />}
3428
</div>
3529
);
3630
};

0 commit comments

Comments
 (0)