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(strapi/search-page): implement the search page #5

Merged
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
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