Skip to content

Commit

Permalink
Merge pull request #104 from official-Trippy/feature/#87
Browse files Browse the repository at this point in the history
feat: ootd 댓글 섹션, 수정 레이아웃
  • Loading branch information
jiohjung98 authored Aug 13, 2024
2 parents ed17420 + 04df094 commit 5843cd7
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 9 deletions.
167 changes: 167 additions & 0 deletions src/app/edit/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// app/edit/[id].tsx
'use client';

import React, { useEffect, useState } from 'react';
import { useRouter, useParams } from 'next/navigation';
import ImageUploader from '@/components/ootd/ImageUploader';
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 { PostRequest, OotdRequest, UploadedImage } from '@/types/ootd';
import Swal from 'sweetalert2';
import { getWeatherStatusInKorean } from '@/constants/weatherTransition';

const EditOotd: React.FC = () => {
const router = useRouter();
const { id } = useParams<{ id: string }>();

const [images, setImages] = useState<UploadedImage[]>([]);
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 [date, setDate] = useState<string>('');
const [weather, setWeather] = useState<any>(null);

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

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,
});
}
}, [data]);

const updatePostMutation = useMutation(
(variables: { postRequest: PostRequest; ootdRequest: OotdRequest }) =>
updateOotdPost(Number(id), variables.postRequest, variables.ootdRequest),
{
onSuccess: () => {
Swal.fire({
icon: 'success',
title: 'OOTD 게시글을 수정하였습니다.',
confirmButtonText: '확인',
confirmButtonColor: '#FB3463',
}).then(() => {
router.push(`/ootd/${id}`);
});
},
onError: () => {
Swal.fire({
icon: 'error',
title: '게시글 수정 오류',
text: '게시글을 수정하는 중 오류가 발생했습니다.',
});
},
}
);

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

const postRequest: PostRequest = {
title: 'ootd 게시물',
body: post,
postType: 'OOTD',
location,
images: images.map(image => ({
imgUrl: image.imgUrl,
accessUri: image.accessUri,
authenticateId: image.authenticateId,
})),
tags,
};

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

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

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

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

return (
<div className="w-full max-w-screen-lg mx-auto px-4 py-8">
<div className="w-full flex justify-end mb-[20px]">
<button
onClick={handleUpdatePost}
className="bg-[#fa3463] rounded-lg flex justify-center items-center px-10 py-2 text-white text-lg"
>
수정하기
</button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<ImageUploader onImagesChange={setImages} initialImages={images} />
<div className="">
<PostInput
onPostChange={setPost}
onTagsChange={setTags}
tags={tags}
initialPost={post}
/>
<div className="space-y-4">
<LocationInput
onLocationChange={(locationData) => {
setLocation(locationData.address);
setLatitude(locationData.lat);
setLongitude(locationData.lng);
setWeather(null);
}}
selectedLocationName={location}
/>
<DateInput onDateChange={setDate} 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>
{weather.avgTemp === '정보 없음'
? '정보 없음'
: `${weather.avgTemp}°C, ${getWeatherStatusInKorean(
weather.status
)}`}
</div>
</div>
) : (
<button
onClick={() => {
if (latitude && longitude && date) {
// Trigger weather fetch
}
}}
className="w-full bg-neutral-100 rounded-lg flex justify-center items-center py-4 text-neutral-500 text-lg"
>
날씨 불러오기
</button>
)}
</div>
</div>
</div>
</div>
);
};

export default EditOotd;
4 changes: 3 additions & 1 deletion src/components/ootd/CommentSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const CommentSection: React.FC<CommentSectionProps> = ({ postId, initialLikeCoun
const [replyTo, setReplyTo] = useState<number | null>(null);
const [replyToNickname, setReplyToNickname] = useState<string | null>(null);
const [isLiked, setIsLiked] = useState<boolean>(false);
const [showComments, setShowComments] = useState<boolean>(false);
const [showLikes, setShowLikes] = useState<boolean>(false);
const [likeList, setLikeList] = useState<any[]>([]);
const [isLoadingLikes, setIsLoadingLikes] = useState<boolean>(false);
Expand All @@ -42,6 +41,9 @@ const CommentSection: React.FC<CommentSectionProps> = ({ postId, initialLikeCoun

const accessToken = Cookies.get("accessToken");

const [showComments, setShowComments] = useState<boolean>(!!accessToken);


const handlePageChange = (pageNumber: number) => {
setCurrentPage(pageNumber);
};
Expand Down
6 changes: 4 additions & 2 deletions src/components/ootd/DateInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import CalendarIcon from '../../../public/icon_calendar.svg';

interface DateInputProps {
onDateChange: (date: string) => void;
initialDate?: string; // 초기 date를 받을 수 있도록 추가
}

const DateInput: React.FC<DateInputProps> = ({ onDateChange }) => {
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
const DateInput: React.FC<DateInputProps> = ({ onDateChange, initialDate }) => {
const initialDateParsed = initialDate ? new Date(initialDate) : null;
const [selectedDate, setSelectedDate] = useState<Date | null>(initialDateParsed);

const handleDateChange = (date: Date | null) => {
if (date) {
Expand Down
5 changes: 3 additions & 2 deletions src/components/ootd/ImageUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import RightArrowIcon from '../../../public/right-arrow.svg';

interface ImageUploaderProps {
onImagesChange: (images: UploadedImage[]) => void;
initialImages?: UploadedImage[]; // 초기 이미지 리스트를 받을 수 있도록 추가
}

const ImageUploader: React.FC<ImageUploaderProps> = ({ onImagesChange }) => {
const [images, setImages] = useState<UploadedImage[]>([]);
const ImageUploader: React.FC<ImageUploaderProps> = ({ onImagesChange, initialImages = [] }) => {
const [images, setImages] = useState<UploadedImage[]>(initialImages);
const [isUploading, setIsUploading] = useState(false);

const handleImageUpload = async (event: ChangeEvent<HTMLInputElement>) => {
Expand Down
3 changes: 2 additions & 1 deletion src/components/ootd/OotdDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ const OotdDetail: React.FC<OotdDetailProps> = ({ id }) => {
className="cursor-pointer"
/>
{isMenuOpen && (
<div className="absolute top-full right-4 mt-4 w-32 bg-white rounded shadow-lg z-10">
<div className="w-[100px] absolute top-full right-4 mt-4 w-32 bg-white rounded shadow-lg z-10">
<div
className="py-4 px-8 text-[#ff4f4f] hover:bg-gray-100 cursor-pointer text-center"
onClick={handleDeleteClick}
Expand All @@ -229,6 +229,7 @@ const OotdDetail: React.FC<OotdDetailProps> = ({ id }) => {
<div
className="py-4 px-8 text-black hover:bg-gray-100 cursor-pointer text-center"
onClick={() => {
router.push(`/edit/${id}`);
}}
>
수정
Expand Down
7 changes: 6 additions & 1 deletion src/components/ootd/PostInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ interface PostInputProps {
onPostChange: (post: string) => void;
onTagsChange: (tags: string[]) => void;
tags: string[];
initialPost?: string; // 초기 post를 받을 수 있도록 추가
}

const PostInput: React.FC<PostInputProps> = ({ onPostChange, onTagsChange, tags }) => {
const PostInput: React.FC<PostInputProps> = ({ onPostChange, onTagsChange, tags, initialPost = '' }) => {
const [post, setPost] = useState<string>(initialPost);
const [tagInput, setTagInput] = useState<string>('');
const [isComposing, setIsComposing] = useState<boolean>(false);
const textareaRef = useRef<HTMLTextAreaElement>(null);
Expand All @@ -18,6 +20,8 @@ const PostInput: React.FC<PostInputProps> = ({ onPostChange, onTagsChange, tags
}, []);

const handlePostChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
const newPost = event.target.value;
setPost(newPost);
onPostChange(event.target.value);
};

Expand Down Expand Up @@ -56,6 +60,7 @@ const PostInput: React.FC<PostInputProps> = ({ onPostChange, onTagsChange, tags
ref={textareaRef}
className="w-full h-64 text-lg border py-4 px-4 rounded resize-none"
onChange={handlePostChange}
value={post}
/>
<div className="relative w-full border py-4 px-4 rounded">
<input
Expand Down
14 changes: 13 additions & 1 deletion src/services/ootd.ts/ootdGet.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import axios from 'axios';
import { OotdDetailGetResponse, OotdGetResponse } from '@/types/ootd';
import { OotdDetailGetResponse, OotdGetResponse, OotdRequest, PostRequest } from '@/types/ootd';
import Cookies from "js-cookie";

const backendUrl: string = process.env.NEXT_PUBLIC_BACKEND_URL || '';
Expand Down Expand Up @@ -108,6 +108,18 @@ export const fetchUserProfile = (memberId: string) => {
};


export const updateOotdPost = async (
id: number,
postRequest: PostRequest,
ootdRequest: OotdRequest
) => {
const response = await axios.patch(`/api/ootd/${id}`, {
postRequest,
ootdRequest,
});
return response.data;
};


axios.interceptors.request.use(
async (config) => {
Expand Down
2 changes: 1 addition & 1 deletion src/types/ootd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export interface PostRequest {
title: string;
body: string;
postType: string;
location: string | null;
location: string;
images: {
imgUrl: string;
accessUri: string;
Expand Down

0 comments on commit 5843cd7

Please sign in to comment.