Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/connect slope api #42

Merged
merged 3 commits into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/app/mobile/slope/[resortId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react';
import WebcamMobileMapPage from '@/views/slop-status/ui/slop-status-page';

const Page = ({ params }: { params: { resortId: string } }) => {
return <WebcamMobileMapPage resortId={+params.resortId} />;
};

export default Page;
12 changes: 9 additions & 3 deletions src/app/mobile/webcam/[key]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { redirect } from 'next/navigation';
import React from 'react';
import WebcamMobileMapPage from '@/views/webcam/ui/webcam-mobile-map-page';
import { DiscoveryData } from '@/entities/discovery';
import { RESORT_DOMAIN } from '@/entities/slop/model';

const Page = ({ params }: { params: { key: string } }) => {
if (!(params?.key in RESORT_DOMAIN)) {
redirect('/not-found');
if (!(params.key in RESORT_DOMAIN)) {
const key = DiscoveryData.find((discovery) => discovery.id === +params.key)?.map;
return (
<WebcamMobileMapPage
resortId={+params.key}
data={RESORT_DOMAIN[key as keyof typeof RESORT_DOMAIN]}
/>
);
}

const domain = RESORT_DOMAIN[params?.key as keyof typeof RESORT_DOMAIN];
Expand Down
8 changes: 8 additions & 0 deletions src/entities/slope/api/get-slope.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { apiClient } from '@/shared/api/base';
import type { SlopeResponse } from '../model';

export const getSlopes = async (resortId: number): Promise<SlopeResponse> => {
const result = await apiClient.get<SlopeResponse>(`/api/slopes/${resortId}`);

return result;
};
1 change: 1 addition & 0 deletions src/entities/slope/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { slopeQueries } from './query/slope.queries';
13 changes: 13 additions & 0 deletions src/entities/slope/api/query/slope.queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { queryOptions } from '@tanstack/react-query';
import { getSlopes } from '../get-slope';

export const slopeQueries = {
all: () => ['slope'],

slopeQueryKey: (resortId: number) => [...slopeQueries.all(), resortId],
slope: (resortId: number) =>
queryOptions({
queryKey: slopeQueries.slopeQueryKey(resortId),
queryFn: () => getSlopes(resortId),
}),
};
2 changes: 2 additions & 0 deletions src/entities/slope/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * as slopeApi from './api';
export * from './model';
1 change: 1 addition & 0 deletions src/entities/slope/model/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type { Level, Slope, Webcam, SlopeResponse } from './model';
34 changes: 34 additions & 0 deletions src/entities/slope/model/model.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export type Level =
| '초급'
| '초중급'
| '중급'
| '중상급'
| '상급'
| '최상급';

export type Slope = {
name: string,
difficulty: Level,
isDayOperating: true,
isNightOperating: true,
isLateNightOperating: true,
isDawnOperating: true,
isMidnightOperating: true
}

export type Webcam = {
name: string,
number: 0,
description: string,
url: string
}

export type SlopeResponse = {
dayOperatingHours: string,
nightOperatingHours: string,
lateNightOperatingHours: string,
dawnOperatingHours: string,
midnightOperatingHours: string,
slopes: Slope[],
webcams: Webcam[]
}
51 changes: 51 additions & 0 deletions src/entities/slope/ui/level-chip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import { cn } from '../../../shared/lib';
import type { Level } from '../model';

const LEVEL: Record<Level, { text: string; color: string }> = {
초급: {
text: '초급',
color: 'bg-sub-2',
},
초중급: {
text: '초중급',
color: 'bg-sub-2',
},
중급: {
text: '중급',
color: 'bg-sub-4',
},
중상급: {
text: '중상급',
color: 'bg-sub-4',
},
상급: {
text: '상급',
color: 'bg-gray-70',
},
최상급: {
text: '최상급',
color: 'bg-gray-70',
},
};

interface LevelChipProps {
className?: string;
level: Level;
}

const LevelChip = ({ level, className }: LevelChipProps) => {
return (
<div
className={cn(
'flex h-[25px] w-[56px] items-center justify-center rounded-[6px] border-[1px] border-white border-opacity-10',
LEVEL[level].color,
className
)}
>
<p className="body1-semibold text-white">{LEVEL[level].text}</p>
</div>
);
};

export default LevelChip;
33 changes: 13 additions & 20 deletions src/features/slop/ui/slop-status-list.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import React from 'react';
import type { Level } from '@/entities/slop/model/model';
import LevelChip from '@/entities/slop/ui/level-chip';
import type { Slope } from '@/entities/slope';
import LevelChip from '@/entities/slope/ui/level-chip';
import CheckIcon from '@/shared/icons/check';
import CloseIcon from '@/shared/icons/close';
import { cn } from '@/shared/lib';
import useSlopStore from '../hooks/useSlopStore';

interface SlopStatusListProps {
list: {
key: string;
name: string;
level: Level;
isOpenDuringDay: boolean;
isOpenDuringWeek: boolean;
isOpenDuringNight: boolean;
}[];
slopes?: Slope[];
}

const SlopStatusList = ({ list }: SlopStatusListProps) => {
const SlopStatusList = ({ slopes }: SlopStatusListProps) => {
const { selectedSlop, setSelectedSlop } = useSlopStore();

const handleSlopClick = ({ id }: { id: string }) => {
Expand Down Expand Up @@ -47,26 +40,26 @@ const SlopStatusList = ({ list }: SlopStatusListProps) => {
</tr>
</thead>
<tbody>
{list.map((item) => (
{slopes?.map((slope) => (
<tr
key={item.key}
className={cn(selectedSlop === item.key && 'bg-main-5')}
onClick={() => handleSlopClick({ id: item.key })}
key={slope.name}
className={cn(selectedSlop === slope.name && 'bg-main-5')}
onClick={() => handleSlopClick({ id: slope.name })}
>
<td className={cn('body1-semibold py-[12px] pl-5 text-left text-gray-80')}>
{item.name}
{slope.name}
</td>
<td className={cn('text-center')}>
<LevelChip level={item.level} className={cn('m-auto')} />
<LevelChip level={slope.difficulty} className={cn('m-auto')} />
</td>
<td className={cn('text-center')}>
<StatusIcon isOpen={item.isOpenDuringDay} className={cn('m-auto')} />
<StatusIcon isOpen={slope.isDayOperating} className={cn('m-auto')} />
</td>
<td className={cn('text-center')}>
<StatusIcon isOpen={item.isOpenDuringWeek} className={cn('m-auto')} />
<StatusIcon isOpen={slope.isNightOperating} className={cn('m-auto')} />
</td>
<td className={cn('pr-5 text-center')}>
<StatusIcon isOpen={item.isOpenDuringNight} className={cn('m-auto')} />
<StatusIcon isOpen={slope.isLateNightOperating} className={cn('m-auto')} />
</td>
</tr>
))}
Expand Down
15 changes: 12 additions & 3 deletions src/views/slop-status/ui/slop-status-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,21 @@ import SlopMap from '@/features/slop/ui/slop-map';
import SlopStatusList from '@/features/slop/ui/slop-status-list';
import { slopQueries } from '@/entities/slop/api';
import { RESORT_DOMAIN } from '@/entities/slop/model';
import { slopeApi } from '@/entities/slope';
import { cn } from '@/shared/lib';

const SlopStatusPage = ({ params }: { params: { key: keyof typeof RESORT_DOMAIN } }) => {
const SlopStatusPage = ({
params,
resortId,
}: {
params?: { key: keyof typeof RESORT_DOMAIN };
resortId?: number;
}) => {
const { ref, style, containerRef } = useMapPinch();

const { data } = useQuery(slopQueries.list(params.key));
const { data: slopeData } = useQuery(slopeApi.slopeQueries.slope(resortId ?? 1));

const { data } = useQuery(slopQueries.list(params?.key ?? 'jisan'));

if (!data) return;

Expand All @@ -27,7 +36,7 @@ const SlopStatusPage = ({ params }: { params: { key: keyof typeof RESORT_DOMAIN
slops={RESORT_DOMAIN[data.key].slops}
/>
</section>
<SlopStatusList list={data.slopes} />
<SlopStatusList slopes={slopeData?.slopes} />
</main>
);
};
Expand Down
2 changes: 1 addition & 1 deletion src/views/webcam/ui/webcam-mobile-map-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import calculateWebcamPosition from '@/features/slop/lib/calculateWebcamPosition
import type { Position, ResortInfo } from '@/entities/slop/model/model';
import { cn } from '@/shared/lib';

const WebCamMobileMapPage = ({ data }: { data: ResortInfo }) => {
const WebCamMobileMapPage = ({ data }: { resortId?: number; data: ResortInfo }) => {
const [cameraPositions, setCameraPositions] = useState<{
[key: string]: Position;
}>({});
Expand Down
Loading