Skip to content

Commit

Permalink
feat(strapi/search-page): implement the search page (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
nathandebalthasar authored Oct 12, 2023
1 parent db331df commit 17b4f14
Show file tree
Hide file tree
Showing 9 changed files with 9,345 additions and 1,330 deletions.
10,434 changes: 9,160 additions & 1,274 deletions apps/trackflix/package-lock.json

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion apps/trackflix/src/api/IApi.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { VideoOnDemand } from './api.interface'
import {
VideoOnDemand,
FetchVideoFilesResponse,
Thumbnail,
} from './api.interface'

export interface IApi {
fetchHighlightedVideos(): Promise<VideoOnDemand[]>
fetchVodFiles(nextToken: string | null): Promise<FetchVideoFilesResponse>
fetchThumbnail(id: string): Promise<Thumbnail>
}
82 changes: 72 additions & 10 deletions apps/trackflix/src/api/StrapiApi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { VideoOnDemand } from './api.interface'
import {
VideoOnDemand,
FetchVideoFilesResponse,
Thumbnail,
} from './api.interface'
import { IApi } from './IApi'
import { StrapiMedia } from './strapi.interface'

Expand All @@ -15,6 +19,23 @@ export class StrapiApi implements IApi {
this.token = token
}

private strapiMediaToVideoOnDemand(video: StrapiMedia): VideoOnDemand {
return {
id: video.id,
src: video.attributes.media_url,
createdAt: video.attributes.createdAt,
updatedAt: video.attributes.updatedAt,
media: {
id: video.id,
title: video.attributes.Name,
description: video.attributes.description,
highlighted: video.attributes.highlighted,
source: 'YOUTUBE',
author: 'Author',
},
} as VideoOnDemand
}

async fetchHighlightedVideos(): Promise<VideoOnDemand[]> {
const response = await fetch(
`${this.baseUrl}/api/vods?filters[highlighted][$eq]=true`,
Expand All @@ -28,14 +49,55 @@ export class StrapiApi implements IApi {
const videos: StrapiMedia[] = await response
.json()
.then((res) => res.data)
return videos.map((video: StrapiMedia) => ({
id: video.id,
title: video.attributes.Name,
description: video.attributes.description,
highlighted: video.attributes.highlighted,
createdAt: video.attributes.createdAt,
updatedAt: video.attributes.updatedAt,
src: video.attributes.media_url,
}))
return videos.map((video: StrapiMedia) =>
this.strapiMediaToVideoOnDemand(video)
)
}

async fetchVodFiles(
nextToken: string | null
): Promise<FetchVideoFilesResponse> {
const response = await fetch(
`${this.baseUrl}/api/vods/?pagination[page]=${
nextToken ? parseInt(nextToken) : 1
}`,
{
headers: {
Authorization: `Bearer ${this.token}`,
},
}
).then((res) => res.json())

const videos: VideoOnDemand[] = response.data.map(
(video: StrapiMedia) => this.strapiMediaToVideoOnDemand(video)
)
const { pageCount, page } = response.meta.pagination

return {
data: videos,
nextToken: page < pageCount ? (page + 1).toString() : null,
}
}

async fetchThumbnail(id: string): Promise<Thumbnail> {
const response = await fetch(
`${this.baseUrl}/api/vods/${id}?populate=Thumbnails`,
{
headers: {
Authorization: `Bearer ${this.token}`,
},
}
).then((res) => res.json())
const thumbnailObj = response.data.attributes?.Thumbnails?.data[0]
const { createdAt, updatedAt } = thumbnailObj.attributes
const { thumbnail } = thumbnailObj?.attributes?.formats

return {
id: thumbnailObj.id,
ext: thumbnail.ext,
src: `${this.baseUrl}${thumbnail.url}`,
createdAt,
updatedAt,
}
}
}
36 changes: 31 additions & 5 deletions apps/trackflix/src/api/api.interface.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
export interface Thumbnail {
src: string
id: string
ext: string
src?: string
createdAt?: string
updatedAt?: string
}

export interface VideoOnDemand {
export enum Source {
SELF = 'SELF',
YOUTUBE = 'YOUTUBE',
LIVESTREAM_SELF = 'LIVESTREAM_SELF',
}

export interface Media {
id: string
title: string
description: string
highlighted: boolean
// sections?: (MediasSections | null)[]
source?: Source | keyof typeof Source
thumbnail?: Thumbnail
createdAt: string
updatedAt: string
src: string
author: string
viewCount?: number
createdAt?: string
updatedAt?: string
}

export interface VideoOnDemand {
id: string
media?: Media
src?: string
createdAt?: string
updatedAt?: string
}

export interface FetchVideoFilesResponse {
data: VideoOnDemand[]
nextToken: string | null
}
41 changes: 18 additions & 23 deletions apps/trackflix/src/pages/search.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React, { useEffect, useState, useMemo } from 'react'
import React, { useEffect, useState, useMemo, useContext } from 'react'
import styled from 'styled-components'
import { AiOutlineSearch } from 'react-icons/ai'
import Layout from '../shared/components/Layout'
import { fetchThumbnail, fetchVodFiles } from '../shared/api'
import { VideoOnDemand, Thumbnail } from '../models'
import { VideoOnDemand } from '../api/api.interface'
import { Thumbnail } from '../models'
import VideoCard from '../shared/components/Card/VideoCard'
import { screenSizes, defaultVideoCardProperties } from '../shared/constants'
import { useWindowDimensions } from '../shared/hooks'
import { CMSContext } from '../context/CMSContext'

const StyledSearchItem = styled.div`
display: flex;
Expand Down Expand Up @@ -78,7 +79,7 @@ const StyledVideoCard = styled.div`
`

type VideoItemProps = {
asset: VideoOnDemand
vod: VideoOnDemand
}

const VideoItem = ({ vod }: VideoItemProps) => {
Expand All @@ -101,19 +102,18 @@ const VideoItem = ({ vod }: VideoItemProps) => {
}
return defaultVideoCardProperties
}, [width])
const { api } = useContext(CMSContext)

useEffect(() => {
;(async () => {
try {
if (vod.media?.thumbnail) {
const data = await fetchThumbnail(vod.media)
setThumbnail({
obj: vod.media?.thumbnail,
url: data as string,
})
}
const data = await api.fetchThumbnail(vod.id)
setThumbnail({
obj: data,
url: data?.src as string,
})
} catch (error) {
console.error('search.tsx(fetchThumbnail):')
console.error('search.tsx(fetchThumbnail):', error)
}
})()
}, [vod])
Expand All @@ -135,25 +135,20 @@ const SearchPage = () => {
const [nextToken, setNextToken] = useState<string | null>(null)
const [searchValue, setSearchValue] = useState<string>('')
const { width } = useWindowDimensions()
const { api } = useContext(CMSContext)

const filterAssets = (elem: VideoOnDemand) =>
elem.media?.title.toLowerCase().includes(searchValue.toLowerCase()) ||
elem.media?.description
.toLowerCase()
elem?.media?.description
?.toLowerCase()
.includes(searchValue.toLowerCase())

useEffect(() => {
;(async () => {
try {
const { data } = await fetchVodFiles(nextToken)
setNextToken(
data?.listVideoOnDemands?.nextToken
? data.listVideoOnDemands.nextToken
: null
)
setVodAssets(
data?.listVideoOnDemands?.items as Array<VideoOnDemand>
)
const response = await api.fetchVodFiles(nextToken)
setNextToken(response?.nextToken ? response?.nextToken : null)
setVodAssets(response.data)
} catch (error) {
console.error('search.tsx(fetchVodFiles):', error)
}
Expand Down
8 changes: 4 additions & 4 deletions apps/trackflix/src/shared/api/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { GRAPHQL_AUTH_MODE } from '@aws-amplify/api-graphql'

async function getAuthMode() {
return null
// await refreshUserCredentials()
// await refreshUserCredentials()

// return Auth.Credentials.getCredSource() !== 'userPool'
// ? GRAPHQL_AUTH_MODE.AWS_IAM
// : GRAPHQL_AUTH_MODE.AMAZON_COGNITO_USER_POOLS
// return Auth.Credentials.getCredSource() !== 'userPool'
// ? GRAPHQL_AUTH_MODE.AWS_IAM
// : GRAPHQL_AUTH_MODE.AMAZON_COGNITO_USER_POOLS
}

async function refreshUserCredentials() {
Expand Down
2 changes: 0 additions & 2 deletions apps/trackflix/src/shared/api/mutate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,7 @@ async function createNewSecuredLinkLog(

const incrementVideoCount = async (media: Media | undefined) => {
// if (!media) return

// const views = media.viewCount ?? 0

// return API.graphql({
// query: updateMedia,
// variables: {
Expand Down
54 changes: 47 additions & 7 deletions apps/trackflix/src/shared/components/Card/VideoCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,25 @@ import styled from 'styled-components'
import { navigate } from 'gatsby'
import TrackitLogo from '../../../assets/logo/trackit-colored.svg'
import Thumbnail from '../Thumbnail'
import {
Thumbnail as IThumbnail,
VideoOnDemand,
} from '../../../api/api.interface'

export const VideoCardContainer = styled.div`
interface VideoStatus {
playing: boolean
played: number
loaded: number
duration: number
seeking: boolean
}

export const VideoCardContainer = styled.div<{
playing: boolean
videoInfos: string
width: number
height: number
}>`
display: flex;
flex-direction: column;
width: ${({ width }) => width}px;
Expand All @@ -22,7 +39,10 @@ export const VideoCardContainer = styled.div`
z-index: ${({ playing }) => (playing ? 6 : 5)};
`

const VideoCardGivenChildrenContainer = styled.div`
const VideoCardGivenChildrenContainer = styled.div<{
playing: boolean
width: number
}>`
display: flex;
flex: 1;
transition: box-shadow 200ms ease-out, transform 200ms ease-out;
Expand All @@ -36,7 +56,9 @@ const VideoCardGivenChildrenContainer = styled.div`
max-height: 170px;
`

const VideoInformations = styled.div`
const VideoInformations = styled.div<{
transparent: boolean
}>`
display: flex;
flex: 1;
flex-direction: column;
Expand Down Expand Up @@ -87,7 +109,9 @@ const ChannelLogo = styled.div`
left: 20px;
`

const CardItemContentContainer = styled.div`
const CardItemContentContainer = styled.div<{
transparent: boolean
}>`
padding: 12px 12px 12px 32px;
display: flex;
position: relative;
Expand All @@ -99,6 +123,22 @@ const CardItemContentContainer = styled.div`
transition: background-color 200ms ease-out;
`

interface VideoCardProps {
video: {
vod: VideoOnDemand
thumbnail?: {
obj: IThumbnail
url: string
}
}
haveSubtitle?: boolean
children?: React.ReactNode
redirectTo?: string | null
videoInfos?: string
cardWidth?: number
cardHeight?: number
}

const VideoCard = ({
video,
haveSubtitle = false,
Expand All @@ -107,7 +147,7 @@ const VideoCard = ({
videoInfos = 'hover',
cardWidth = 360,
cardHeight = 200,
}) => {
}: VideoCardProps) => {
const [videoStatus, setVideoStatus] = useState<VideoStatus>({
playing: false,
played: 0,
Expand All @@ -122,10 +162,10 @@ const VideoCard = ({
...updatedData,
})
const handleMouseLeave = () => {
updateVideoStatus({ playing: false })
updateVideoStatus({ ...videoStatus, playing: false })
}
const handleMouseEnter = () => {
updateVideoStatus({ playing: true })
updateVideoStatus({ ...videoStatus, playing: true })
}

return children ? (
Expand Down
Loading

0 comments on commit 17b4f14

Please sign in to comment.