Skip to content

Commit

Permalink
Merge pull request #33 from f-lab-edu/feature/28-now-playing-movie-re…
Browse files Browse the repository at this point in the history
…view

[FEATURE] 상영중인 영화 리뷰 목록 UI 추가
  • Loading branch information
ag502 authored Dec 7, 2024
2 parents 2fcac91 + 8711b1e commit 4b25879
Show file tree
Hide file tree
Showing 17 changed files with 351 additions and 13 deletions.
12 changes: 12 additions & 0 deletions apps/web/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import GenresApi from "@/entities/genres/api/genres-api";
import { reviewsQueryKeys } from "@/entities/reviews";
import ReviewsApi from "@/entities/reviews/api/reviews-api";
import { NowPlayingMovieList } from "@/features/get-now-playing-movie-list";
import { NowPlayingMovieReviewList } from "@/features/get-now-playing-movie-review-list";
import { PopularMovieList } from "@/features/get-popular-movie-list";
import { UpcomingMovieList } from "@/features/get-upcoming-movie-list";
import { popularMovieListTitle } from "@/pages/home";
Expand All @@ -25,6 +26,17 @@ export default function Home({ dehydratedState }: InferGetServerSidePropsType<ty
<link href="/favicon.ico" rel="icon" />
</Head>

<Container>
<Row>
<Col lg={12} md={12} sm={4}>
<Text as="h2" className={popularMovieListTitle} size="xl" weight="bold">
리뷰
</Text>
<NowPlayingMovieReviewList />
</Col>
</Row>
</Container>

<Container>
<Row>
<Col lg={12} md={12} sm={4}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export interface ReviewAuthorDetails {
name: string;
name: string | null;
username: string;
avatar_path: string;
rating: string;
rating: string | null;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export interface ReviewAuthorDetailsDTO {
name: string;
name: string | null;
username: string;
avatarPath: string;
rating: string;
rating: string | null;
}
3 changes: 1 addition & 2 deletions apps/web/src/entities/reviews/api/reviews-api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { localHttp } from "@/shared/api";
import { camelCaseObjMapper } from "@/shared/lib";

import { NowPlayingMovieListReviewsParams } from "./request-types";
import { NowPlayingMovieListReviewsDTO } from "./response-types";
Expand All @@ -26,6 +25,6 @@ export default class ReviewsApi {
},
...axiosConfig,
})
.then((res) => camelCaseObjMapper(res.data));
.then((res) => res.data);
}
}
1 change: 1 addition & 0 deletions apps/web/src/entities/reviews/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./api";
export * from "./models";
export * from "./ui";
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class NowPlayingMovieReviewModel {
createdAt: string;
updatedAt: string;
reviewUrl: string;
authorDetails: ReviewAuthorDetailsDTO;
private authorDetails: ReviewAuthorDetailsDTO;

constructor(data: NowPlayingMovieReviewDTO) {
this.movieId = data.movieId;
Expand Down
16 changes: 12 additions & 4 deletions apps/web/src/entities/reviews/models/review-author.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ReviewAuthorDetailsDTO } from "../api";

export class ReviewAuthorModel {
name: string;
userName: string;
private name: string | null;
private userName: string;
avatarPath: string;
rating: string;
rating: string | null;

constructor(data: ReviewAuthorDetailsDTO) {
this.name = data.name;
Expand All @@ -13,7 +13,15 @@ export class ReviewAuthorModel {
this.rating = data.rating;
}

get UserName() {
return this.name ? this.name : this.userName;
}

get UserNameFirstLetter() {
return this.userName[0]!;
return this.UserName[0];
}

get ScoreMaximumFive() {
return this.rating ? String(parseInt(this.rating) / 2) : null;
}
}
1 change: 1 addition & 0 deletions apps/web/src/entities/reviews/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./now-playing-movie-review-card/now-playing-movie-review-card";
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { createVar, style } from "@vanilla-extract/css";
import { calc } from "@vanilla-extract/css-utils";

import { globalThemeVars, themeColorContract } from "@/shared/styles";

const cardHeight = createVar();
const cardPadding = createVar();

export const reviewCardContainer = style({
vars: {
[cardHeight]: "182px",
[cardPadding]: globalThemeVars.space["3"],
},
backgroundColor: themeColorContract.color.background,
border: `1px solid ${themeColorContract.color.gray20}`,
borderRadius: globalThemeVars.radius.lg,
height: cardHeight,
padding: cardPadding,
});

export const reviewCardTitle = style({
display: "flex",
justifyContent: "space-between",
});

export const reviewCardContent = style({
display: "flex",
gap: globalThemeVars.space["2"],
padding: `${globalThemeVars.space["3"]} 0`,
height: "100%",
});

export const reviewCardPosterWrapper = style({
flex: "1 0 0",
overflow: "hidden",
borderRadius: globalThemeVars.radius.sm,
height: "fit-content",
});

export const reviewCardContentWrapper = style({
flex: "4 0 0",
});

export const reviewMovieTitle = style({
marginBottom: globalThemeVars.space["1"],
});

export const reviewContent = style({
overflow: "hidden",
textOverflow: "ellipsis",
display: "-webkit-box",
WebkitBoxOrient: "vertical",
WebkitLineClamp: 4,
lineHeight: "1.5em",
maxHeight: calc(cardHeight).divide(2).add(cardPadding).toString(),
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { AspectRatio } from "@repo/ui/aspect-ratio";
import Image from "next/image";

import { NowPlayingMovieReviewModel } from "@/entities/reviews";
import { Text } from "@/shared/ui/text";

import {
reviewCardContainer,
reviewCardTitle,
reviewCardContent,
reviewMovieTitle,
reviewContent,
reviewCardPosterWrapper,
reviewCardContentWrapper,
} from "./now-playing-movie-review-card.css";

export function NowPlayingMovieReviewCard({ review }: { review: NowPlayingMovieReviewModel }) {
return (
<article className={reviewCardContainer}>
<div className={reviewCardTitle}>
<Text color="tertiaryText" size="sm">
{review.AuthorDetails.UserName}
</Text>
<Text color="tertiaryText" size="sm">
{review.AuthorDetails.ScoreMaximumFive}
</Text>
</div>

<div className={reviewCardContent}>
<div className={reviewCardPosterWrapper}>
<AspectRatio ratio={10 / 7}>
<Image
alt={`${review.movieTitle} poster image`}
height={100}
src={`${process.env.NEXT_PUBLIC_TMDB_RESOURCE_BASE_URL}/t/p/w200${review.posterPath}`}
style={{ width: "100%", height: "100%" }}
width={100}
/>
</AspectRatio>
</div>
<div className={reviewCardContentWrapper}>
<Text as="h1" className={reviewMovieTitle} size="md" weight="medium">
{review.movieTitle}
</Text>
<Text className={reviewContent} color="tertiaryText" lineHeight="5" size="md">
{review.content}
</Text>
</div>
</div>
</article>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ const swiperBreakPoints: SwiperOptions["breakpoints"] = {
export function NowPlayingMovieList() {
const { data: nowPlayingMovieList, status: nowPlayingMovieListStatus } = useNowPlayingMovieListQuery();

// useQueries(movieListQueries.nowPlayingMovieList());

if (nowPlayingMovieListStatus === "pending") {
return <div>Loading...</div>;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./ui";
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./now-playing-movie-review-list/now-playing-movie-review-list";
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Swiper, SwiperSlide } from "swiper/react";
import { SwiperOptions } from "swiper/types";

import { useNowPlayingMovieListReviewsQuery } from "@/entities/reviews";
import { NowPlayingMovieReviewCard } from "@/entities/reviews";
import { screenBreakPoints } from "@/shared/styles";

const swiperBreakPoints: SwiperOptions["breakpoints"] = {
[parseInt(screenBreakPoints.sm)]: { slidesPerView: 2, spaceBetween: 12 },
[parseInt(screenBreakPoints.md)]: { slidesPerView: 3, spaceBetween: 16 },
};

export function NowPlayingMovieReviewList() {
const { data, status } = useNowPlayingMovieListReviewsQuery();

if (status === "pending") {
return <div>Loading...</div>;
}

if (status === "error") {
return <div>Error...</div>;
}

return (
<Swiper breakpoints={swiperBreakPoints} slidesPerView={1} spaceBetween={8}>
{data.Reviews.map((review) => {
return (
<SwiperSlide key={review.reviewId}>
<NowPlayingMovieReviewCard review={review} />
</SwiperSlide>
);
})}
</Swiper>
);
}
27 changes: 27 additions & 0 deletions apps/web/src/shared/styles/tokens/radius.css.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
export const radius = {
/**
* @description `0px`
*/
none: "0",
/**
* @description `0.125rem` // `16 * 0.125 = 2px`
*/
sm: "0.125rem",
/**
* @description `0.25rem` // `16 * 0.25 = 4px`
*/
base: "0.25rem",
/**
* @description `0.375rem // 16 * 0.375 = 6px`
*/
md: "0.375rem",
/**
* @description `0.5rem` // `16 * 0.5 = 8px`
*/
lg: "0.5rem",
/**
* @description `0.75rem` // `16 * 0.75 = 12px`
*/
xl: "0.75rem",
/**
* @description `1rem` // `16 * 1 = 16px`
*/
"2xl": "1rem",
/**
* @description `1.5rem` // `16 * 1.5 = 24px`
*/
"3xl": "1.5rem",
/**
* @description `9999px`
*/
full: "9999px",
};
Loading

0 comments on commit 4b25879

Please sign in to comment.