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
43 changes: 30 additions & 13 deletions app/[locale]/apps/[application]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { pick } from "lodash"
import { notFound } from "next/navigation"
import { getMessages, setRequestLocale } from "next-intl/server"
import {
getMessages,
getTranslations,
setRequestLocale,
} from "next-intl/server"

import { ChainName } from "@/lib/types"

Expand Down Expand Up @@ -58,6 +62,9 @@ const Page = async ({
const { locale, application } = await params
setRequestLocale(locale)

// Get translations
const t = await getTranslations({ locale, namespace: "page-apps" })

// Get i18n messages
const allMessages = await getMessages({ locale })
const requiredNamespaces = getRequiredNamespacesForPage("/apps")
Expand Down Expand Up @@ -115,9 +122,9 @@ const Page = async ({
const diffInMs = now.getTime() - date.getTime()
const diffInDays = Math.floor(diffInMs / (1000 * 60 * 60 * 24))

if (diffInDays === 0) return "Today"
if (diffInDays === 1) return "1 day ago"
return `${diffInDays} days ago`
if (diffInDays === 0) return t("page-apps-today")
if (diffInDays === 1) return t("page-apps-one-day-ago")
return t("page-apps-days-ago", { days: diffInDays })
}

return (
Expand Down Expand Up @@ -194,7 +201,7 @@ const Page = async ({
eventName: "visit",
}}
>
Visit {app.name}
{t("page-apps-visit-app", { appName: app.name })}
</ButtonLink>
<div className="flex flex-row justify-between gap-4">
<div className="flex h-fit flex-row flex-wrap gap-4">
Expand Down Expand Up @@ -250,7 +257,9 @@ const Page = async ({
{nextApp && (
<LinkBox className="group flex flex-row items-center rounded-lg hover:bg-background-highlight sm:hidden">
<div className="mr-2 flex flex-col text-right">
<p className="text-sm text-gray-500">See next</p>
<p className="text-sm text-gray-500">
{t("page-apps-see-next")}
</p>
<p className="text-primary group-hover:text-primary-hover">
{nextApp.name}
</p>
Expand All @@ -275,7 +284,9 @@ const Page = async ({
{nextApp && (
<LinkBox className="group hidden flex-row items-center rounded-lg p-3 hover:bg-background-highlight sm:flex">
<div className="mr-2 flex flex-col text-right">
<p className="text-nowrap text-sm text-gray-500">See next</p>
<p className="text-nowrap text-sm text-gray-500">
{t("page-apps-see-next")}
</p>
<p className="text-primary group-hover:text-primary-hover">
{nextApp.name}
</p>
Expand All @@ -299,25 +310,31 @@ const Page = async ({
<div className="grid grid-cols-1 grid-rows-[auto_1fr] gap-10 bg-background-highlight px-4 py-10 md:grid-cols-[minmax(0,1fr)_auto] md:px-8">
<p className="max-w-3xl">{app.description}</p>
<div className="flex h-fit w-full flex-col gap-4 rounded-2xl border bg-background p-8 md:row-span-2 md:w-44">
<h3 className="text-lg">Info</h3>
<h3 className="text-lg">{t("page-apps-info-title")}</h3>
<div>
<p className="text-sm text-body-medium">Founded</p>
<p className="text-sm text-body-medium">
{t("page-apps-info-founded")}
</p>
<p className="text-sm">
{new Date(app.dateOfLaunch).getFullYear()}
</p>
</div>
<div>
<p className="text-sm text-body-medium">Creator</p>
<p className="text-sm text-body-medium">
{t("page-apps-info-creator")}
</p>
<p className="text-sm">{app.parentCompany}</p>
</div>
<div>
<p className="text-sm text-body-medium">Last updated</p>
<p className="text-sm text-body-medium">
{t("page-apps-info-last-updated")}
</p>
<p className="text-sm">{getTimeAgo(app.lastUpdated)}</p>
</div>
</div>
{app.screenshots.length > 0 && (
<div className="flex flex-col gap-4">
<h3 className="text-2xl">Gallery</h3>
<h3 className="text-2xl">{t("page-apps-gallery-title")}</h3>
<ScreenshotSwiper
screenshots={app.screenshots}
appName={app.name}
Expand All @@ -329,7 +346,7 @@ const Page = async ({
{relatedApps.length > 0 && (
<div className="flex flex-col px-4 py-10 md:px-8">
<div className="flex w-full flex-col items-center gap-8 rounded-2xl bg-gradient-to-t from-blue-500/20 from-10% to-blue-500/5 to-90% p-12 px-4 md:px-8">
<h2>More apps like this</h2>
<h2>{t("page-apps-more-apps-like-this")}</h2>
<div className="flex w-full flex-col gap-4 lg:flex-row">
{relatedApps.map((relatedApp) => (
<div
Expand Down
9 changes: 6 additions & 3 deletions app/[locale]/apps/_components/AppsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import { trackCustomEvent } from "@/lib/utils/matomo"

import AppCard from "./AppCard"

import useTranslation from "@/hooks/useTranslation"

const AppsTable = ({ apps }: { apps: AppData[] }) => {
const { t } = useTranslation("page-apps")
const [filterBy, setFilterBy] = useState("All")

const subCategories = useMemo(
Expand All @@ -41,7 +44,7 @@ const AppsTable = ({ apps }: { apps: AppData[] }) => {
<div className="flex flex-col gap-7">
<div className="flex flex-row items-end justify-between border-b pb-2 sm:items-center">
<div className="flex flex-col items-start gap-2 sm:flex-row sm:items-center">
<p className="whitespace-nowrap">Filter by</p>
<p className="whitespace-nowrap">{t("page-apps-filter-by")}</p>
<Select
value={filterBy}
onValueChange={(value) => {
Expand All @@ -61,7 +64,7 @@ const AppsTable = ({ apps }: { apps: AppData[] }) => {
value="All"
className="cursor-pointer hover:bg-primary-low-contrast"
>
All
{t("page-apps-filter-all")}
</SelectItem>
{subCategories.map((subCategory) => (
<SelectItem
Expand All @@ -77,7 +80,7 @@ const AppsTable = ({ apps }: { apps: AppData[] }) => {
</div>
<div>
<p className="text-body-medium">
Showing{" "}
{t("page-apps-showing")}{" "}
<span className="text-body">
(
{filteredApps.length === apps.length
Expand Down
18 changes: 14 additions & 4 deletions app/[locale]/apps/_components/CategoriesNav.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { getTranslations } from "next-intl/server"

import TabNav from "@/components/ui/TabNav"

import { slugify } from "@/lib/utils/url"

import { appsCategories } from "@/data/apps/categories"

const CategoriesNav = ({ activeCategory = "" }: { activeCategory: string }) => {
const CategoriesNav = async ({
activeCategory = "",
}: {
activeCategory: string
}) => {
const t = await getTranslations("page-apps")

const items = Object.values(appsCategories).map(
({ name, icon: Icon, slug }) => ({
key: name,
label: name,
key: slug,
label: t(name),
href: `/apps/categories/${slug}`,
icon: <Icon className="h-4 w-4" />,
})
Expand All @@ -15,7 +25,7 @@ const CategoriesNav = ({ activeCategory = "" }: { activeCategory: string }) => {
return (
<TabNav
items={items}
activeKey={activeCategory}
activeKey={slugify(activeCategory)}
customEventOptions={{
eventCategory: "categories_page",
eventAction: "navigation",
Expand Down
14 changes: 7 additions & 7 deletions app/[locale]/apps/_components/SuggestAnApp.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { getTranslations } from "next-intl/server"

import { ButtonLink } from "@/components/ui/buttons/Button"

const SuggestAnApp = () => {
const SuggestAnApp = async () => {
const t = await getTranslations("page-apps")
return (
<div className="flex flex-col items-center gap-4 rounded-2xl bg-radial-a p-12">
<h2>Suggest an app</h2>
<p>
We&apos;re always looking for new apps to add to our list. If you know
of an app that you think should be on the list, please let us know.
</p>
<h2>{t("page-apps-suggest-an-app-title")}</h2>
<p>{t("page-apps-suggest-an-app-description")}</p>
<ButtonLink
href="https://submitapp.paperform.co/"
variant="outline"
className="w-fit"
hideArrow
>
Suggest an app
{t("page-apps-suggest-an-app-button")}
</ButtonLink>
</div>
)
Expand Down
7 changes: 5 additions & 2 deletions app/[locale]/apps/_components/TopApps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ import AppCard from "./AppCard"

import { useBreakpointValue } from "@/hooks/useBreakpointValue"
import { useIsClient } from "@/hooks/useIsClient"
import useTranslation from "@/hooks/useTranslation"

interface TopAppsProps {
appsData: Record<AppCategory, AppData[]>
}

const TopApps = ({ appsData }: TopAppsProps) => {
const { t } = useTranslation("page-apps")
const isClient = useIsClient()
const cardStyling = useBreakpointValue({
base: {
Expand Down Expand Up @@ -119,7 +122,7 @@ const TopApps = ({ appsData }: TopAppsProps) => {
})()}
</div>
<p className="text-lg font-bold text-body no-underline group-hover:text-primary">
{category}
{t(appsCategories[category].name)}
</p>
</div>
<div>
Expand All @@ -129,7 +132,7 @@ const TopApps = ({ appsData }: TopAppsProps) => {
size="sm"
className="w-fit"
>
<p className="text-sm">See all</p>
<p className="text-sm">{t("page-apps-see-all")}</p>
</Button>
</div>
</div>
Expand Down
25 changes: 17 additions & 8 deletions app/[locale]/apps/categories/[catetgoryName]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { pick } from "lodash"
import { notFound } from "next/navigation"
import { getMessages, setRequestLocale } from "next-intl/server"
import {
getMessages,
getTranslations,
setRequestLocale,
} from "next-intl/server"

import { AppCategoryEnum } from "@/lib/types"

Expand Down Expand Up @@ -52,6 +56,8 @@ const Page = async ({

const [appsData] = await loadData()

const t = await getTranslations({ locale, namespace: "page-apps" })

// Get i18n messages
const allMessages = await getMessages({ locale })
const requiredNamespaces = getRequiredNamespacesForPage("/apps")
Expand Down Expand Up @@ -96,13 +102,15 @@ const Page = async ({
/
</BreadcrumbSeparator>
<BreadcrumbItem>
<BreadcrumbPage>{category.name.toUpperCase()}</BreadcrumbPage>
<BreadcrumbPage>
{t(category.name).toUpperCase()}
</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
}
title={category.name}
subtitle={category.description}
title={t(category.name)}
subtitle={t(category.description)}
/>

<div className="flex flex-col gap-4 px-4 md:px-8">
Expand All @@ -111,15 +119,15 @@ const Page = async ({

<MainArticle className="flex flex-col gap-32 py-10">
<div className="flex flex-col px-4 md:px-8">
<h2>Highlights</h2>
<h2>{t("page-apps-highlights-title")}</h2>
<AppsHighlight
apps={highlightedApps}
matomoCategory={`category_page`}
/>
</div>

<div className="flex flex-col px-4 md:px-8">
<AppsTable apps={appsData[category.name]} />
<AppsTable apps={appsData[categoryEnum]} />
</div>

<div className="flex flex-col px-4 md:px-8">
Expand All @@ -137,6 +145,7 @@ export async function generateMetadata({
params: Promise<{ locale: string; catetgoryName: string }>
}) {
const { locale, catetgoryName } = await params
const t = await getTranslations({ locale, namespace: "page-apps" })

// Normalize slug to lowercase
const normalizedSlug = catetgoryName.toLowerCase()
Expand All @@ -156,8 +165,8 @@ export async function generateMetadata({
notFound()
}

const title = category.metaTitle
const description = category.metaDescription
const title = t(category.metaTitle)
const description = t(category.metaDescription)

return await getMetadata({
locale,
Expand Down
Loading