Skip to content

Commit

Permalink
Merge pull request #110 from official-Trippy/feature/#87
Browse files Browse the repository at this point in the history
Feature/#87
  • Loading branch information
jiohjung98 authored Aug 28, 2024
2 parents b295064 + f266a1f commit 07a3997
Show file tree
Hide file tree
Showing 23 changed files with 834 additions and 172 deletions.
3 changes: 3 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"zustand": "^4.5.2"
},
"devDependencies": {
"@types/event-source-polyfill": "^1.0.5",
"@types/js-cookie": "^3.0.6",
"@types/node": "^20",
"@types/react": "^18",
Expand Down
5 changes: 5 additions & 0 deletions public/bookmark-fill.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icon_bookmark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
230 changes: 192 additions & 38 deletions src/app/edit/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// app/edit/[id].tsx
'use client';

import React, { useEffect, useState } from 'react';
Expand All @@ -8,10 +7,13 @@ import PostInput from '@/components/ootd/PostInput';
import LocationInput from '@/components/ootd/LocationInput';
import DateInput from '@/components/ootd/DateInput';
import { useQuery, useMutation } from 'react-query';
import { fetchOotdPostDetail, updateOotdPost } from '@/services/ootd.ts/ootdGet';;
import { fetchOotdPostDetail, updateOotdPost, updatePost } from '@/services/ootd.ts/ootdGet';
import { PostRequest, OotdRequest, UploadedImage } from '@/types/ootd';
import Swal from 'sweetalert2';
import { getWeatherStatusInKorean } from '@/constants/weatherTransition';
import { fetchWeather } from '@/services/ootd.ts/weather';
import { getCoordinatesFromAddress } from '@/constants/geocode';
import ImageChanger from '@/components/ootd/ImageChanger';

const EditOotd: React.FC = () => {
const router = useRouter();
Expand All @@ -21,34 +23,136 @@ const EditOotd: React.FC = () => {
const [post, setPost] = useState<string>('');
const [tags, setTags] = useState<string[]>([]);
const [location, setLocation] = useState<string>('');
const [latitude, setLatitude] = useState<number>(0);
const [longitude, setLongitude] = useState<number>(0);
const [latitude, setLatitude] = useState<number | null>(null);
const [longitude, setLongitude] = useState<number | null>(null);
const [date, setDate] = useState<string>('');
const [weather, setWeather] = useState<any>(null);
const [postId, setPostId] = useState<number | null>(null);
const [ootdId, setOotdId] = useState<number | null>(null);

// 상태 변경 여부를 추적하는 상태
const [hasChanges, setHasChanges] = useState<boolean>(false);

// Fetching existing OOTD post details
const { data, isLoading, error } = useQuery(['ootdPostDetail', id], () =>
fetchOotdPostDetail(Number(id))
);

const formatDateString = (dateString: string | null) => {
if (!dateString) return ''; // null이나 undefined일 경우 빈 문자열 반환

// dateString이 'yyyy-MM-dd' 형식일 경우에만 변환
const dateParts = dateString.split('-');
if (dateParts.length === 3) {
const [year, month, day] = dateParts;
return `${year}${month.padStart(2, '0')}${day.padStart(2, '0')}`;
}
return dateString; // 형식이 다를 경우 원본 문자열 반환
};


const formatDateForApi = (dateString: string | null) => {
if (!dateString) return ''; // null이나 undefined일 경우 빈 문자열 반환

// 'yyyyMMdd' 형식의 문자열을 'yyyy-MM-dd' 형식으로 변환
const year = dateString.slice(0, 4);
const month = dateString.slice(4, 6);
const day = dateString.slice(6, 8);
return `${year}-${month}-${day}`;
};


useEffect(() => {
if (data) {
const ootdItem = data.result;
setImages(ootdItem.post.images);
setPost(ootdItem.post.body);
setTags(ootdItem.post.tags);
setLocation(ootdItem.post.location);
setDate(ootdItem.post.createDateTime);
setWeather({
status: ootdItem.ootd.weatherStatus,
avgTemp: ootdItem.ootd.weatherTemp,
});
if (data && data.isSuccess) {
const postData = data.result.post;
const ootdData = data.result.ootd;

console.log(postData.images);

if (postData && ootdData) {
setPostId(postData.id);
setOotdId(ootdData.id);

setImages(postData.images);
setPost(postData.body);
setTags(postData.tags);
setLocation(postData.location);
setDate(formatDateString(ootdData.date || ''));
setWeather({
status: ootdData.weatherStatus,
avgTemp: ootdData.weatherTemp,
});

console.log(formatDateString(ootdData.date)); // 변환된 날짜 확인

// 주소를 좌표로 변환하여 latitude와 longitude를 설정합니다.
getCoordinatesFromAddress(postData.location).then(coordinates => {
if (coordinates) {
setLatitude(coordinates.lat);
setLongitude(coordinates.lng);
}
});
} else {
console.error('Post or OOTD data is missing');
}
}
}, [data]);

useEffect(() => {
console.log('렌더링된 이미지 상태: ', images); // 상태 업데이트 후의 이미지 상태를 로그합니다.
}, [images]);

// 비동기적으로 상태가 설정되었는지 확인
useEffect(() => {
if (images.length > 0) {
console.log('렌더링된 이미지 상태 (비동기 확인): ', images);
}
}, [images]);

useEffect(() => {
if (hasChanges && latitude !== null && longitude !== null && date) {
handleFetchWeather();
}
}, [hasChanges, latitude, longitude, date]);

const weatherMutation = useMutation(
(variables: { latitude: number; longitude: number; date: string }) =>
fetchWeather(variables.latitude, variables.longitude, variables.date),
{
onSuccess: (data) => {
setWeather(data.result);
},
onError: () => {
Swal.fire({
icon: 'error',
title: '날씨 정보를 불러올 수 없습니다.',
text: '날씨와 온도를 직접 선택해주세요.',
confirmButtonText: '확인',
confirmButtonColor: '#FB3463',
});
},
}
);

const handleFetchWeather = () => {
if (latitude === null || longitude === null || !date) {
Swal.fire({
icon: 'error',
title: '입력 오류',
text: '위치와 날짜를 모두 입력해주세요.',
});
return;
}
weatherMutation.mutate({ latitude, longitude, date });
};

const updatePostMutation = useMutation(
(variables: { postRequest: PostRequest; ootdRequest: OotdRequest }) =>
updateOotdPost(Number(id), variables.postRequest, variables.ootdRequest),
async (variables: { postRequest: PostRequest; ootdRequest: OotdRequest }) => {
if (postId === null || ootdId === null) {
throw new Error('Post ID or OOTD ID is missing');
}
await updatePost(postId, variables.postRequest);
return updateOotdPost(ootdId, variables.ootdRequest);
},
{
onSuccess: () => {
Swal.fire({
Expand All @@ -71,8 +175,50 @@ const EditOotd: React.FC = () => {
);

const handleUpdatePost = () => {
const formattedDate = date.replace(/-/g, '');

if (postId === null || ootdId === null) {
Swal.fire({
icon: 'error',
title: '오류',
text: '포스트 ID 또는 OOTD ID가 없습니다.',
});
return;
}

if (images.length === 0) {
Swal.fire({
icon: 'error',
title: '이미지 오류',
text: '이미지를 업로드해주세요.',
confirmButtonText: '확인',
confirmButtonColor: '#FB3463',
});
return;
}

if (post.trim() === '') {
Swal.fire({
icon: 'error',
title: '문구 작성 오류',
text: 'OOTD 문구를 작성해주세요.',
confirmButtonText: '확인',
confirmButtonColor: '#FB3463',
});
return;
}

if (tags.length < 3) {
Swal.fire({
icon: 'error',
title: '태그 오류',
text: '태그를 3개 이상 등록해주세요.',
confirmButtonText: '확인',
confirmButtonColor: '#FB3463',
});
return;
}

const formattedDateForApi = formatDateForApi(date);

const postRequest: PostRequest = {
title: 'ootd 게시물',
body: post,
Expand All @@ -84,25 +230,39 @@ const EditOotd: React.FC = () => {
authenticateId: image.authenticateId,
})),
tags,
memberId: data?.result.member.memberId || '',
};

const ootdRequest: OotdRequest = {
area: weather?.area || '',
weatherStatus: weather?.status || '',
weatherTemp: weather?.avgTemp === '정보 없음' ? '' : weather?.avgTemp || '',
detailLocation: location,
date: formattedDate,
date: formattedDateForApi,
};

updatePostMutation.mutate({ postRequest, ootdRequest });
};


const handleLocationChange = (locationData: { address: string; lat: number; lng: number }) => {
setLocation(locationData.address);
setLatitude(locationData.lat);
setLongitude(locationData.lng);
setHasChanges(true);
};

const handleDateChange = (newDate: string) => {
setDate(formatDateString(newDate));
setHasChanges(true);
};

if (isLoading) {
return <div>Loading...</div>;
return null;
}

if (error || !data) {
return <div>Error loading post data</div>;
return null;
}

return (
Expand All @@ -116,7 +276,7 @@ const EditOotd: React.FC = () => {
</button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<ImageUploader onImagesChange={setImages} initialImages={images} />
<ImageChanger onImagesChange={setImages} initialImages={images} />
<div className="">
<PostInput
onPostChange={setPost}
Expand All @@ -126,15 +286,13 @@ const EditOotd: React.FC = () => {
/>
<div className="space-y-4">
<LocationInput
onLocationChange={(locationData) => {
setLocation(locationData.address);
setLatitude(locationData.lat);
setLongitude(locationData.lng);
setWeather(null);
}}
onLocationChange={handleLocationChange}
selectedLocationName={location}
/>
<DateInput onDateChange={setDate} initialDate={date} />
<DateInput
onDateChange={handleDateChange}
initialDate={date}
/>
{weather ? (
<div className="w-full bg-neutral-100 rounded-lg flex justify-center items-center py-4 text-neutral-500 text-lg">
<div>
Expand All @@ -147,11 +305,7 @@ const EditOotd: React.FC = () => {
</div>
) : (
<button
onClick={() => {
if (latitude && longitude && date) {
// Trigger weather fetch
}
}}
onClick={handleFetchWeather}
className="w-full bg-neutral-100 rounded-lg flex justify-center items-center py-4 text-neutral-500 text-lg"
>
날씨 불러오기
Expand Down
Loading

0 comments on commit 07a3997

Please sign in to comment.