Skip to content

Commit

Permalink
Merge pull request #4 from AmorGakCo/feat/Group
Browse files Browse the repository at this point in the history
Feat/group 그룹 관련 페이지 및 기능
  • Loading branch information
phnml1 authored Oct 5, 2024
2 parents e6943ea + 782f119 commit 8b14d4d
Show file tree
Hide file tree
Showing 62 changed files with 2,562 additions and 281 deletions.
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,23 @@
"@hookform/resolvers": "^3.9.0",
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-checkbox": "^1.1.1",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-toggle-group": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.3",
"@tanstack/react-query": "^5.51.15",
"@tanstack/react-query-devtools": "^5.51.15",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cva": "^0.0.0",
"jose": "^5.7.0",
"date-fns": "^3.6.0",
"lucide-react": "^0.424.0",
"next": "14.2.5",
"react": "^18",
"react-day-picker": "8.10.1",
"react-dom": "^18",
"react-hook-form": "^7.52.2",
"react-kakao-maps-sdk": "^1.1.27",
Expand Down
3 changes: 3 additions & 0 deletions public/activated_group.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/detail_location_icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/distance.png
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/location_on.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/myLocation.png
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/past_group.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/right_arrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/search.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 0 additions & 7 deletions src/app/(afterLogin)/group/[name]/page.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use client'
export default function Default() {
return <div className="w-full h-20 bg-black">
왜안되지
</div>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
'use client'
export default function Error () {
return (<div className="mt-8 w-full h-[200px] bg-gray-200">지도를 로드할 수 없습니다.</div>)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use client'

export default function Loading () {
return (<div className="mt-8 w-full h-[200px] bg-gray-200">위치 정보를 가져오고 있습니다..</div>)
}
67 changes: 67 additions & 0 deletions src/app/(afterLogin)/group/detail/[groupId]/@location/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use client';
import { Map, MapMarker } from 'react-kakao-maps-sdk';

export default function Location() {
const center = { lng: 126.9748397, lat: 37.5703901 };
const marker = { lng: 126.9748397, lat: 37.5703901 };
const address = '서울특별시 종로구 신문로1가 23';
return (
<div className="mt-8 w-full h-[200px] bg-gray-200">
<Map // 지도를 표시할 Container
center={center}
style={{
// 지도의 크기
width: '100%',
height: '100%',
flex: '1',
display: 'flex',
}}
level={5}
draggable = {false}
// 지도의 확대 레벨
// onDragEnd={(map) => {
// const lat = map.getCenter().getLat();
// const lng = map.getCenter().getLng();
// setCurLocation((prev) => ({
// ...prev,
// center: { lat: lat, lng: lng },
// radius: 500,
// }));
// }}
// onZoomChanged={(map) => {
// const lat = map.getCenter().getLat();
// const lng = map.getCenter().getLng();
// console.log(lat, lng);
// setCurLocation((prev) => ({
// ...prev,
// center: { lat: lat, lng: lng },
// radius: 500,
// }));
// }}
>
<MapMarker // 마커를 생성합니다
image={{
src: `/mapMarker.svg`, // 마커이미지의 주소입니다
size: {
width: 24,
height: 32,
}, // 마커이미지의 크기입니다
options: {
offset: {
x: 27,
y: 69,
}, // 마커이미지의 옵션입니다. 마커의 좌표와 일치시킬 이미지 안에서의 좌표를 설정합니다.
},
}}
position={{
// 마커가 표시될 위치입니다
lat: marker.lat,
lng: marker.lng,
}}
>
<div className="w-auto h-auto p-1">{address}</div>
</MapMarker>
</Map>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use client'
import { GroupDetailData } from "@/app/_types/Api";
import { Button } from "@/components/ui/button";
import { useQuery } from "@tanstack/react-query";
import { fetchGroupData } from "../_lib/fetchGroupData";

export function ButtonGroup ({groupId}:{groupId: number}) {
const { data, error } = useQuery<
GroupDetailData, // 성공 시 반환될 데이터 타입
Error, // 에러 타입 (여기서는 Error로 지정)
GroupDetailData, // 캐시된 데이터를 사용할 때의 타입 (보통 첫 번째와 동일하게 사용)
[string, number] // queryKey의 타입 (string과 number로 이루어진 튜플)
>({
queryKey: ["groupDetail", groupId],
queryFn: fetchGroupData,
staleTime: 60 * 1000, // fresh -> stale, 5분이라는 기준
gcTime: 300 * 1000,
});
return (<div className="flex flex-col gap-4">
<Button>모임 위치 인증</Button>
<Button>지각 알림</Button>
<Button>장소 변경 요청</Button>
<Button className={`bg-[#FF2950] hover:bg-[#FF2950]/70`}>
{`'${data!.name}'`} 탈퇴
</Button>
</div>)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use client'
import Image from 'next/image';
import { fetchGroupData } from '../_lib/fetchGroupData';
import { useEffect } from 'react';
import { GroupDetailData } from '@/app/_types/Api';
import { useQuery } from '@tanstack/react-query';
const GroupAddress = ({ groupId }: { groupId: number }) => {
const { data, error } = useQuery<
GroupDetailData, // 성공 시 반환될 데이터 타입
Error, // 에러 타입 (여기서는 Error로 지정)
GroupDetailData, // 캐시된 데이터를 사용할 때의 타입 (보통 첫 번째와 동일하게 사용)
[string, number] // queryKey의 타입 (string과 number로 이루어진 튜플)
>({
queryKey: ["groupDetail", groupId],
queryFn: fetchGroupData,
staleTime: 60 * 1000, // fresh -> stale, 5분이라는 기준
gcTime: 300 * 1000,
});
console.log(data);
return (
<div className="flex justify-between">
<div>모임 위치</div>
<div className="flex gap-[4.5px] items-center">
<Image
src="/detail_location_icon.svg"
alt="location"
width={7}
height={10}
/>

<div className="text-secondary text-xs">{data?.address}</div>
</div>
</div>
);
};
export default GroupAddress;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use client'
import { GroupDetailData } from "@/app/_types/Api";
import { useQuery } from "@tanstack/react-query";
import { fetchGroupData } from "../_lib/fetchGroupData";

const GroupDescription = ({groupId}: {groupId: number}) => {
const { data, error } = useQuery<
GroupDetailData, // 성공 시 반환될 데이터 타입
Error, // 에러 타입 (여기서는 Error로 지정)
GroupDetailData, // 캐시된 데이터를 사용할 때의 타입 (보통 첫 번째와 동일하게 사용)
[string, number] // queryKey의 타입 (string과 number로 이루어진 튜플)
>({
queryKey: ["groupDetail", groupId],
queryFn: fetchGroupData,
staleTime: 60 * 1000, // fresh -> stale, 5분이라는 기준
gcTime: 300 * 1000,
});
return (
<div>
<div>모임 설명</div>
<div className="pt-3 pb-6">{data?.description}</div>
</div>
);
};
export default GroupDescription;
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use client'
import { Avatar, AvatarImage } from "@/components/ui/avatar";
import { Dialog, DialogTrigger } from "@/components/ui/dialog";
import GroupMembersModal from "./GroupMembersModal";
import Image from "next/image";
import { useQuery } from "@tanstack/react-query";
import { GroupDetailData } from "@/app/_types/Api";
import { fetchGroupData } from "../_lib/fetchGroupData";
export default function GroupMembers({groupId}:{groupId:number}) {
const { data, error } = useQuery<
GroupDetailData, // 성공 시 반환될 데이터 타입
Error, // 에러 타입 (여기서는 Error로 지정)
GroupDetailData, // 캐시된 데이터를 사용할 때의 타입 (보통 첫 번째와 동일하게 사용)
[string, number] // queryKey의 타입 (string과 number로 이루어진 튜플)
>({
queryKey: ["groupDetail", groupId],
queryFn: fetchGroupData,
staleTime: 60 * 1000, // fresh -> stale, 5분이라는 기준
gcTime: 300 * 1000,
});
const maxGroupMember = (data?.groupMembers.length!>=5)? 5: data?.groupMembers.length;
return (
<div className="flex justify-between items-center w-full h-10">
<div>모임 인원</div>
<div className="flex relative h-10">
{data?.groupMembers?.slice(0, maxGroupMember).map((member, index) => {
const zIndex = `z-${index + 1}0`;
return (
<Avatar
key={member.memberId}
className={`w-10 h-10 top-0 absolute ${zIndex}`}
style={{ right: `${index * 24 + 14}px` }}
>
<AvatarImage src={`${member.imgUrl}`} />
</Avatar>
);
})}
<Dialog>
<DialogTrigger asChild>
<Image
src="/right_arrow.svg"
alt={'group members'}
width={6}
height={12}
className="cursor-pointer"
/>
</DialogTrigger>
<GroupMembersModal/>
</Dialog>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { Avatar, AvatarImage } from '@/components/ui/avatar';
import { DialogContent, DialogTitle } from '@/components/ui/dialog';

export default function GroupMembersModal() {
return (
<>
<DialogTitle className = 'hidden'></DialogTitle>
<DialogContent className="flex flex-col gap-2 py-6 px-4 max-h-96 ">
<div className='overflow-auto'>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
<div className="flex w-full h-14 gap-4 items-center">
<Avatar>
<AvatarImage className="w-10 h-10 rounded-full" src="/coin.svg" />
</Avatar>

<div>하준숴이</div>
</div>
</div>
</DialogContent>
</>
);
}
Loading

0 comments on commit 8b14d4d

Please sign in to comment.