Skip to content
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
1 change: 1 addition & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ jobs:
cat <<EOF > apps/web/.env
NEXT_PUBLIC_SITE_URL="${{ secrets.INFISICAL_WEB_APP_URL }}"
NEXT_PUBLIC_API_URL="${{ secrets.INFISICAL_API_URL }}"
NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT_ID="${{ secrets.INFISICAL_GOOGLE_ADSENSE_CLIENT_ID }}"
NEXT_PUBLIC_REVENUECAT_API_KEY="${{ secrets.INFISICAL_REVENUECAT_WEB_API_KEY }}"
NEXT_PUBLIC_FIREBASE_API_KEY="${{ secrets.INFISICAL_FIREBASE_API_KEY }}"
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN="${{ secrets.INFISICAL_FIREBASE_AUTH_DOMAIN }}"
Expand Down
2 changes: 2 additions & 0 deletions apps/web/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ NEXT_PUBLIC_API_URL=
# ---------------------------------------------------------------------------- #

# --------------------------------- SERVICES --------------------------------- #
# ADS
NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT_ID=
# ANALYTICS
ANALYTICS_URL=
ANALYTICS_ID=
Expand Down
15 changes: 15 additions & 0 deletions apps/web/src/app/[lang]/(app)/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Link } from '@/lib/i18n/navigation';
import { upperFirst } from 'lodash';
import { Metadata } from 'next';
import { SupportedLocale } from '@libs/i18n';
import { ConsentButton } from '@/components/Ads/ConsentButton';

export const generateMetadata = async (props: {
params: Promise<{
Expand Down Expand Up @@ -163,6 +164,20 @@ const About = async (props: {
<p>{t('pricing.intro')}</p>
<p className="text-xs italic text-muted-foreground">{t('pricing.subdescription')}</p>
</section>

<section id="legal" className="w-full flex flex-col gap-4 px-4 max-w-xl">
<h2 className="text-center font-semibold text-3xl text-accent-yellow">
{t('legal.label')}
</h2>
<p>{t('legal.description')}</p>
<Link
href="/legal/privacy-policy"
className="font-bold text-accent-pink hover:underline underline-offset-2"
>
{t('legal.privacyPolicy')}
</Link>
<ConsentButton />
</section>
{/* BUSINESS MODEL */}
<section id="businessmodel" className="w-full flex flex-col gap-4 px-4 max-w-xl">
<h2 className="text-center font-semibold text-3xl text-accent-yellow">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use client';

import AdBanner from '@/components/Ads/AdBanner';
import { useAuth } from '@/context/auth-context';

export const MovieAds = () => {
const { session } = useAuth();

if (session) return null;

return <AdBanner dataAdSlot="2164978961" />;
};
127 changes: 70 additions & 57 deletions apps/web/src/app/[lang]/(app)/film/[film_id]/(default)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,42 @@ import { getMovie } from '@/api/server/medias';
import { getTmdbImage } from '@/lib/tmdb/getTmdbImage';
import { JustWatchWidget } from '@/components/JustWatch/JustWatchWidgetScript';
import { MovieCasting } from './_components/MovieCasting';
import { MovieAds } from './_components/MovieAds';

export async function generateMetadata(
props: {
params: Promise<{
lang: SupportedLocale;
film_id: string;
}>;
}
): Promise<Metadata> {
export async function generateMetadata(props: {
params: Promise<{
lang: SupportedLocale;
film_id: string;
}>;
}): Promise<Metadata> {
const { lang, film_id } = await props.params;
const t = await getTranslations({ locale: lang as SupportedLocale });
const { id: movieId} = getIdFromSlug(film_id);
const { id: movieId } = getIdFromSlug(film_id);
const { data: movie, error } = await getMovie(lang, movieId);
if (error || !movie) {
return { title: upperFirst(t('common.messages.film_not_found')) };
}
return {
title: t('pages.film.metadata.title', { title: movie.title!, year: new Date(String(movie.releaseDate)).getFullYear() }),
title: t('pages.film.metadata.title', {
title: movie.title!,
year: new Date(String(movie.releaseDate)).getFullYear(),
}),
description: truncate(
movie.directors
? t('pages.film.metadata.description', {
title: movie.title!,
directors: new Intl.ListFormat(lang, { style: 'long', type: 'conjunction' }).format(movie.directors.map((director) => director.name ?? '')),
year: new Date(String(movie.releaseDate)).getFullYear(),
overview: movie.overview || '',
}) : t('pages.film.metadata.description_no_director', {
title: movie.title!,
year: new Date(String(movie.releaseDate)).getFullYear(),
overview: movie.overview || ''
}),
{ length: siteConfig.seo.description.limit }
title: movie.title!,
directors: new Intl.ListFormat(lang, { style: 'long', type: 'conjunction' }).format(
movie.directors.map((director) => director.name ?? ''),
),
year: new Date(String(movie.releaseDate)).getFullYear(),
overview: movie.overview || '',
})
: t('pages.film.metadata.description_no_director', {
title: movie.title!,
year: new Date(String(movie.releaseDate)).getFullYear(),
overview: movie.overview || '',
}),
{ length: siteConfig.seo.description.limit },
),
alternates: generateAlternates(lang, `/film/${movie.slug}`),
openGraph: {
Expand All @@ -51,35 +56,36 @@ export async function generateMetadata(
description: truncate(
movie.directors
? t('pages.film.metadata.description', {
title: movie.title!,
directors: new Intl.ListFormat(lang, { style: 'long', type: 'conjunction' }).format(movie.directors.map((director) => director.name ?? '')),
year: new Date(String(movie.releaseDate)).getFullYear(),
overview: movie.overview || '',
}) : t('pages.film.metadata.description_no_director', {
title: movie.title!,
year: new Date(String(movie.releaseDate)).getFullYear(),
overview: movie.overview || ''
}),
{ length: siteConfig.seo.description.limit }
title: movie.title!,
directors: new Intl.ListFormat(lang, { style: 'long', type: 'conjunction' }).format(
movie.directors.map((director) => director.name ?? ''),
),
year: new Date(String(movie.releaseDate)).getFullYear(),
overview: movie.overview || '',
})
: t('pages.film.metadata.description_no_director', {
title: movie.title!,
year: new Date(String(movie.releaseDate)).getFullYear(),
overview: movie.overview || '',
}),
{ length: siteConfig.seo.description.limit },
),
url: `${siteConfig.url}/${lang}/film/${movie.slug}`,
images: movie.posterPath ? [
{ url: getTmdbImage({ path: movie.posterPath, size: 'w500' }) },
] : undefined,
images: movie.posterPath
? [{ url: getTmdbImage({ path: movie.posterPath, size: 'w500' }) }]
: undefined,
type: 'video.movie',
locale: lang,
}
},
};
}

export default async function MoviePage(
props: {
params: Promise<{
lang: SupportedLocale;
film_id: string;
}>;
}
) {
export default async function MoviePage(props: {
params: Promise<{
lang: SupportedLocale;
film_id: string;
}>;
}) {
const { lang, film_id } = await props.params;
const t = await getTranslations();
const { id: movieId } = getIdFromSlug(film_id);
Expand All @@ -96,23 +102,29 @@ export default async function MoviePage(
datePublished: movie.releaseDate ?? undefined,
dateModified: new Date().toISOString(),
duration: movie.runtime ? toISO8601Duration(movie.runtime) : undefined,
director: movie.directors
?.map(director => ({
'@type': 'Person',
name: director.name ?? undefined,
image: director.profilePath ? getTmdbImage({ path: director.profilePath, size: 'w500' }) : undefined,
})),
aggregateRating: movie.voteAverage ? {
'@type': 'AggregateRating',
ratingValue: movie.voteAverage,
ratingCount: movie.voteCount ?? 0,
bestRating: 10,
worstRating: 1,
} : undefined,
director: movie.directors?.map((director) => ({
'@type': 'Person',
name: director.name ?? undefined,
image: director.profilePath
? getTmdbImage({ path: director.profilePath, size: 'w500' })
: undefined,
})),
aggregateRating: movie.voteAverage
? {
'@type': 'AggregateRating',
ratingValue: movie.voteAverage,
ratingCount: movie.voteCount ?? 0,
bestRating: 10,
worstRating: 1,
}
: undefined,
};
return (
<>
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<div className="@container/movie-details flex flex-col gap-4">
<div className="flex flex-col @4xl/movie-details:flex-row gap-4 justify-between">
<div>
Expand All @@ -128,8 +140,9 @@ export default async function MoviePage(
className="min-w-[20%]"
/>
</div>
<MovieAds />
<div>
<h2 className="text-lg font-medium">{upperFirst(t('common.messages.cast'))}</h2>
<h2 className="text-lg font-medium">{upperFirst(t('common.messages.cast'))}</h2>
<MovieCasting movie={movie} />
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use client';

import AdBanner from '@/components/Ads/AdBanner';
import { useAuth } from '@/context/auth-context';

export const PersonAds = () => {
const { session } = useAuth();

if (session) return null;

return <AdBanner dataAdSlot="2164978961" />;
};
58 changes: 31 additions & 27 deletions apps/web/src/app/[lang]/(app)/person/[person_id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { notFound } from 'next/navigation';
import { getIdFromSlug } from '@/utils/get-id-from-slug';
import { getTranslations } from 'next-intl/server';
import { truncate, upperFirst } from 'lodash';
import { truncate } from 'lodash';
import { Metadata } from 'next';
import { siteConfig } from '@/config/site';
import { generateAlternates } from '@/lib/i18n/routing';
Expand All @@ -10,52 +9,57 @@ import { getPerson } from '@/api/server/medias';
import { getTmdbImage } from '@/lib/tmdb/getTmdbImage';
import { WidgetPersonFilms } from './_components/WidgetPersonFilms';
import { WidgetPersonTvSeries } from './_components/WidgetPersonTvSeries';
import { PersonAds } from './_components/PersonAds';

export async function generateMetadata(
props: {
params: Promise<{
lang: SupportedLocale;
person_id: string;
}>;
}
): Promise<Metadata> {
export async function generateMetadata(props: {
params: Promise<{
lang: SupportedLocale;
person_id: string;
}>;
}): Promise<Metadata> {
const { lang, person_id } = await props.params;
const t = await getTranslations({ locale: lang });
const { id } = getIdFromSlug(person_id);
const person = await getPerson(lang, id);
return {
title: t('pages.person.metadata.title', { name: person.name!, department: person.knownForDepartment! }),
description: person.biography ? truncate(person.biography, { length: siteConfig.seo.description.limit }) : undefined,
title: t('pages.person.metadata.title', {
name: person.name!,
department: person.knownForDepartment!,
}),
description: person.biography
? truncate(person.biography, { length: siteConfig.seo.description.limit })
: undefined,
alternates: generateAlternates(lang, `/person/${person.slug}`),
openGraph: {
siteName: siteConfig.name,
title: `${person.name} • ${person.knownForDepartment} • ${siteConfig.name}`,
description: person.biography ? truncate(person.biography, { length: siteConfig.seo.description.limit }) : undefined,
description: person.biography
? truncate(person.biography, { length: siteConfig.seo.description.limit })
: undefined,
url: `${siteConfig.url}/${lang}/person/${person.slug}`,
images: person.profilePath ? [
{ url: getTmdbImage({ path: person.profilePath, size: 'w500'}) },
] : undefined,
images: person.profilePath
? [{ url: getTmdbImage({ path: person.profilePath, size: 'w500' }) }]
: undefined,
type: 'profile',
locale: lang,
}
},
};
}

export default async function Person(
props: {
params: Promise<{
lang: SupportedLocale;
person_id: string;
}>;
}
) {
export default async function Person(props: {
params: Promise<{
lang: SupportedLocale;
person_id: string;
}>;
}) {
const { person_id } = await props.params;
const { id } = getIdFromSlug(person_id);
return (
<div className='flex flex-col items-center'>
<div className='max-w-7xl w-full'>
<div className="flex flex-col items-center">
<div className="max-w-7xl w-full">
<WidgetPersonFilms personId={id} personSlug={person_id} />
<WidgetPersonTvSeries personId={id} personSlug={person_id} />
<PersonAds />
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use client';

import AdBanner from '@/components/Ads/AdBanner';
import { useAuth } from '@/context/auth-context';

export const TvSeriesAds = () => {
const { session } = useAuth();

if (session) return null;

return <AdBanner dataAdSlot="2164978961" />;
};
Loading
Loading