Skip to content

Commit

Permalink
Frontend/feat: View game details page (#11)
Browse files Browse the repository at this point in the history
* chore: add @headlessui/react and @heroicons/react

* feat: update shared/card component

* docs: update README.md

* feat: add root link shared/header

* feat: implement shared/modal

* feat: implement shared/rating

* feat: implement game details page
  • Loading branch information
joaoGabriel55 authored Nov 10, 2023
1 parent 74fd49c commit f593ae7
Show file tree
Hide file tree
Showing 18 changed files with 327 additions and 23 deletions.
8 changes: 7 additions & 1 deletion frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next

## Getting Started

First, run the development server:
First create `.env.local` variables file:

```bash
cp .env.example .env.local
```

Second, run the development server:

```bash
npm run dev
Expand Down
25 changes: 25 additions & 0 deletions frontend/package-lock.json

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

6 changes: 4 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev -p 4000",
"build": "next build",
"start": "next start",
"start": "next start -p 4000",
"lint": "next lint",
"test": "vitest",
"test:coverage": "vitest run --coverage"
},
"dependencies": {
"@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.0.18",
"@tanstack/react-query": "^4.36.1",
"@types/react-dom": "18.2.7",
"autoprefixer": "10.4.15",
Expand Down
3 changes: 0 additions & 3 deletions frontend/src/app/assets/star.svg

This file was deleted.

7 changes: 7 additions & 0 deletions frontend/src/app/game/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import GameDetails from '@/views/game-details/game-details'

type Params = { params: { id: string } }

export default function Game({ params }: Params) {
return <GameDetails id={params.id} />
}
2 changes: 1 addition & 1 deletion frontend/src/shared/components/card/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type Props = Children & { className?: string }
export default function Card({ children, className }: Props) {

return (
<div className={classNames("rounded-lg bg-tertiary p-8 border-primary", className)}>
<div className={classNames("rounded-lg bg-tertiary p-8", className)}>
{children}
</div>
)
Expand Down
15 changes: 12 additions & 3 deletions frontend/src/shared/components/header/header.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import Image from 'next/image'
import Search from '../search/search'
import Link from 'next/link'

export default function Header() {
return (
<header className='p-8 bg-primary flex flex-col md:flex-row gap-4 md:justify-between items-center relative bg-cm42'>
<Image className='md:ml-20' src='/codeminer-main-logo.svg' alt='CM42 Media Critic, white logo' width={376} height={80} />
<header className="p-8 bg-primary flex flex-col md:flex-row gap-4 md:justify-between items-center relative bg-cm42">
<Link href="/">
<Image
className="md:ml-20"
src="/codeminer-main-logo.svg"
alt="CM42 Media Critic, white logo"
width={376}
height={80}
/>
</Link>
<Search />
</header>
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default function LoadingSpinner() {
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
strokeWidth="4"
></circle>
<path
className="opacity-75"
Expand Down
93 changes: 93 additions & 0 deletions frontend/src/shared/components/modal/modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
'use client'

import { Dialog, Transition } from '@headlessui/react'
import classNames from 'classnames'
import { Fragment, useRef } from 'react'

export type Props = {
title: string
open: boolean
children: React.ReactNode
onSubmit: () => void
onClose: () => void
}

export default function Modal({
title,
children,
open,
onSubmit,
onClose,
}: Props) {
const cancelButtonRef = useRef(null)
const buttonClassName =
'text-center font-semibold px-3 py-2 rounded-lg transition duration-200 w-full sm:w-auto inline-flex justify-center'

return (
<Transition.Root show={open} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
initialFocus={cancelButtonRef}
onClose={onClose}
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</Transition.Child>

<div className="fixed inset-0 z-10 w-screen overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-tertiary text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg">
<div className="bg-tertiary px-4 pb-4 pt-5 sm:p-6 sm:pb-4">
<div className="sm:flex sm:items-start">
<div className="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left">
<Dialog.Title as="h1" className="font-semibold text-xl">
{title}
</Dialog.Title>
<div className="mt-2">{children}</div>
</div>
</div>
</div>
<div className="bg-tertiary px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6 items-center gap-2">
<button
className={classNames(
buttonClassName,
'bg-primary hover:bg-secondary',
)}
onClick={onSubmit}
>
Confirm
</button>
<button
className={classNames(buttonClassName, 'hover:bg-zinc-800')}
onClick={onClose}
ref={cancelButtonRef}
>
Cancel
</button>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
)
}
23 changes: 23 additions & 0 deletions frontend/src/shared/components/rating/rating.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { StarIcon } from '@heroicons/react/24/solid'

type Props = {
stars: number
size?: number
}

export default function Rating({ stars, size }: Props) {
const starSize = size ?? 24

return (
<div className='flex'>
{Array.from({ length: stars }).map((_, index) => (
<StarIcon
key={index}
className="mx-1"
width={starSize}
height={starSize}
/>
))}
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use client'

import Modal from '@/shared/components/modal/modal'
import { useState } from 'react'

export default function AddMyReview() {
const [open, setOpen] = useState(false)

return (
<>
<button
className="bg-primary text-center font-semibold py-2 rounded-lg transition duration-200 hover:bg-secondary"
onClick={() => setOpen(true)}
>
Add my review
</button>
<Modal
open={open}
title="Add my review"
onClose={() => setOpen(false)}
onSubmit={() => setOpen(false)}
>
<p className="text-sm">
Will be available soon.
</p>
</Modal>
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Image from "next/image"

type Props = { title: string, url: string }

export default function MediaCover({ title, url }: Props) {
return (
<Image
className="rounded-lg"
src={url ?? '/placeholder.jpg'}
alt={url ? title : 'Placeholder'}
width={218}
height={218}
style={{ height: '442px', width: '380px' }}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type Props = { title: string; synopsis: string }

export default function MediaInfo({ title, synopsis }: Props) {
return (
<>
<h1 className="text-4xl font-semibold mb-2">{title}</h1>
<p className="text-ellipsis overflow-hidden line-clamp-3">{synopsis}</p>
<a href="#">
<p className="font-semibold text-primary">See more</p>
</a>
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Rating from '@/shared/components/rating/rating';

type Props = { title: string; rating: number }

export default function MediaRating({ title, rating }: Props) {
return (
<div className="flex items-end justify-between">
<h2 className="text-3xl">{title}</h2>
<div className="flex">
<Rating stars={rating} size={42} />
</div>
</div>
)
}
23 changes: 23 additions & 0 deletions frontend/src/views/game-details/components/reviews/review-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Card from '@/shared/components/card/card'
import Rating from '@/shared/components/rating/rating'

export default function ReviewCard() {
return (
<Card className="px-6 py-5 flex flex-col gap-4">
<div className="flex gap-2 justify-between">
<h3 className="font-medium">Zezin movies</h3>
<Rating stars={3} />
</div>
<p className="text-ellipsis overflow-hidden line-clamp-5 text-sm">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor...
</p>
<div className='flex justify-between text-xs'>
<span>OCT 23, 2022</span>
<a className="text-primary font-semibold" href='#'>Read more</a>
</div>
</Card>
)
}
17 changes: 17 additions & 0 deletions frontend/src/views/game-details/components/reviews/reviews.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ReviewCard from './review-card'

export default function Reviews({ title }: { title: string }) {
return (
<div>
<div className='mb-7 flex justify-between items-end font-medium'>
<h1 className='font-semibold text-2xl'>{title}</h1>
<a href="#">View all</a>
</div>
<div className="flex gap-8">
{Array.from({ length: 3 }).map((_, index) => (
<ReviewCard key={index} />
))}
</div>
</div>
)
}
Loading

0 comments on commit f593ae7

Please sign in to comment.