Skip to content

Commit

Permalink
Trending page
Browse files Browse the repository at this point in the history
  • Loading branch information
scottcorgan committed Apr 19, 2023
1 parent ee5a981 commit 9235317
Show file tree
Hide file tree
Showing 7 changed files with 1,766 additions and 209 deletions.
42 changes: 22 additions & 20 deletions app/components/ModelList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ interface ModelListType {
selectedFilter?: string | undefined | null;
setSelectedFilter?: (arg: React.ChangeEvent<HTMLSelectElement>) => void | undefined;
showFilters?: boolean;
showMenu?: boolean;
selectedSortBy?: "newest" | "popular" | "following";
onSortChange?: (arg: string) => void | undefined;
user?: User | null | undefined;
profile: ProfileWithSocials | null;
emptyMessage?: string;
categories: Category[];
hideSortOrder?: boolean;
}

const ModelsListComponent = ({
Expand All @@ -41,11 +41,11 @@ const ModelsListComponent = ({
selectedFilter = null,
setSelectedFilter = undefined,
showFilters = true,
showMenu = true,
selectedSortBy = "newest",
onSortChange = undefined,
user = null,
profile,
hideSortOrder = false,
emptyMessage = "No results",
}: ModelListType) => {
const location = useLocation();
Expand Down Expand Up @@ -87,24 +87,26 @@ const ModelsListComponent = ({
return (
<div>
<ul className="list-none p-0 m-0 flex gap-3 items-center justify-center md:justify-end mb-5">
<li>
<ModelSortDropdown
icon={<ArrowsUpDownIcon className="w-4- h-4" />}
renderItem={(item) => item.title}
items={[
{
title: "Newest",
href: `${location.pathname}?${newestParams}`,
default: !searchParams.get("sortDirection") || searchParams.get("sortDirection") === "desc",
},
{
title: "Oldest",
href: `${location.pathname}?${oldestParams}`,
default: searchParams.get("sortDirection") === "asc",
},
]}
/>
</li>
{hideSortOrder ? null : (
<li>
<ModelSortDropdown
icon={<ArrowsUpDownIcon className="w-4- h-4" />}
renderItem={(item) => item.title}
items={[
{
title: "Newest",
href: `${location.pathname}?${newestParams}`,
default: !searchParams.get("sortDirection") || searchParams.get("sortDirection") === "desc",
},
{
title: "Oldest",
href: `${location.pathname}?${oldestParams}`,
default: searchParams.get("sortDirection") === "asc",
},
]}
/>
</li>
)}

<li>
<ModelSortDropdown
Expand Down
110 changes: 110 additions & 0 deletions app/routes/__layout/popular.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import type { LoaderFunction, MetaFunction } from "@remix-run/node";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { startCase } from "lodash";
import { getSession } from "~/auth.server";

import type { User } from "@supabase/supabase-js";
import { getModels } from "~/services/models";
import type { ProfileWithSocials } from "~/services/profile";
import { getProfileWithSocials } from "~/services/profile";
import type { Category, Counts, Model } from "@prisma/client";
import { db } from "~/utils/db.server";
import { MODELS_LIMIT } from "~/utils/constants";
import ModelList from "~/components/ModelList";
import { getSortFilter } from "~/utils/loader";

export const meta: MetaFunction<LoaderData> = ({ data, location }) => {
const d = data as LoaderData;
const searchParams = new URLSearchParams(location.search);

const total = d.counts.reduce((total, count) => {
return total + count.count;
}, 0);

const title = searchParams.get("tags")
? `#${searchParams.get("tags")} Models | ToneHunt`
: searchParams.get("filter")
? `${startCase(searchParams.get("filter") as string)} Models | ToneHunt`
: "ToneHunt | Sound Better!";

const description = `Explore over ${total} Neural Amp Modeler models, including ${
d.counts.find((count) => count.name === "amps")?.count
} amps, and ${d.counts.find((count) => count.name === "pedals")?.count} pedals.`;

// TODO: update this for new layout

return {
title,
description,

"og:title": title,
// "og:image": "http://euro-travel-example.com/thumbnail.jpg", // TODO
"og:url": `${location.pathname}${location.search}`,
// "twitter:card": "summary_large_image", // TODO

// <!-- Non-Essential, But Recommended -->
"og:description": description,
"twitter:image:alt": description,
};
};

export type LoaderData = {
user?: User | null;
models: Model[];
profile: ProfileWithSocials | null;
counts: Counts[];
total: number;
page: number;
categories: Category[];
};

export const loader: LoaderFunction = async ({ request }) => {
const { session } = await getSession(request);

const user = session?.user;
const url = new URL(request.url);

const profile = await getProfileWithSocials(session);

const { offset, sortDirection, page, categoryId, categories } = await getSortFilter(url);

const countsReq = await db.counts.findMany();

const modelsReq = getModels({
limit: MODELS_LIMIT,
next: offset,
categoryId,
sortBy: "popular",
sortDirection,
});

const [counts, models] = await Promise.all([countsReq, modelsReq]);

return json<LoaderData>({
counts,
user,
models: models.data,
total: models.total,
profile,
page,
categories,
});
};

export default function Index() {
const data = useLoaderData<LoaderData>();

return (
<ModelList
data={data.models}
categories={data.categories}
total={data.total}
currentPage={data.page}
limit={MODELS_LIMIT}
user={data.user}
profile={data.profile}
hideSortOrder
/>
);
}
111 changes: 111 additions & 0 deletions app/routes/__layout/trending.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import type { LoaderFunction, MetaFunction } from "@remix-run/node";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { startCase } from "lodash";
import { getSession } from "~/auth.server";

import type { User } from "@supabase/supabase-js";
import { getModels } from "~/services/models";
import type { ProfileWithSocials } from "~/services/profile";
import { getProfileWithSocials } from "~/services/profile";
import type { Category, Counts, Model } from "@prisma/client";
import { db } from "~/utils/db.server";
import { MODELS_LIMIT } from "~/utils/constants";
import ModelList from "~/components/ModelList";
import { getSortFilter } from "~/utils/loader";

export const meta: MetaFunction<LoaderData> = ({ data, location }) => {
const d = data as LoaderData;
const searchParams = new URLSearchParams(location.search);

const total = d.counts.reduce((total, count) => {
return total + count.count;
}, 0);

const title = searchParams.get("tags")
? `#${searchParams.get("tags")} Models | ToneHunt`
: searchParams.get("filter")
? `${startCase(searchParams.get("filter") as string)} Models | ToneHunt`
: "ToneHunt | Sound Better!";

const description = `Explore over ${total} Neural Amp Modeler models, including ${
d.counts.find((count) => count.name === "amps")?.count
} amps, and ${d.counts.find((count) => count.name === "pedals")?.count} pedals.`;

// TODO: update this for new layout

return {
title,
description,

"og:title": title,
// "og:image": "http://euro-travel-example.com/thumbnail.jpg", // TODO
"og:url": `${location.pathname}${location.search}`,
// "twitter:card": "summary_large_image", // TODO

// <!-- Non-Essential, But Recommended -->
"og:description": description,
"twitter:image:alt": description,
};
};

export type LoaderData = {
user?: User | null;
models: Model[];
profile: ProfileWithSocials | null;
counts: Counts[];
total: number;
page: number;
categories: Category[];
};

export const loader: LoaderFunction = async ({ request }) => {
const { session } = await getSession(request);

const user = session?.user;
const url = new URL(request.url);

const profile = await getProfileWithSocials(session);

const { offset, sortDirection, page, categoryId, categories } = await getSortFilter(url);

const countsReq = await db.counts.findMany();

const modelsReq = getModels({
limit: MODELS_LIMIT,
next: offset,
categoryId,
sortBy: "popular",
sortDirection,
lastNDays: 3,
});

const [counts, models] = await Promise.all([countsReq, modelsReq]);

return json<LoaderData>({
counts,
user,
models: models.data,
total: models.total,
profile,
page,
categories,
});
};

export default function Index() {
const data = useLoaderData<LoaderData>();

return (
<ModelList
data={data.models}
categories={data.categories}
total={data.total}
currentPage={data.page}
limit={MODELS_LIMIT}
user={data.user}
profile={data.profile}
hideSortOrder
/>
);
}
8 changes: 7 additions & 1 deletion app/routes/sign-up.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Alert from "~/components/ui/Alert";
import { Link } from "@remix-run/react";
import type { Counts } from "@prisma/client";
import { ModelListCountTitle } from "~/components/routes/ModelListPage";
import { isNotAllowed } from "~/utils/username";

export const meta: MetaFunction = ({ location }) => ({
title: "Sign Up | ToneHunt",
Expand Down Expand Up @@ -52,15 +53,20 @@ export const action: ActionFunction = async ({ request, context }) => {
return json<ActionData>({ error: "Invalid username" });
}

const usernameErrorMessage = "Username already exist. Please try a new one.";

try {
if (isNotAllowed(username)) {
return json<ActionData>({ error: usernameErrorMessage }, { status: 500 });
}

const usernameFlag = await db.profile.findUnique({
where: {
username: username,
},
});

if (usernameFlag) {
const usernameErrorMessage = "Username already exist. Please try a new one.";
return json<ActionData>({ error: usernameErrorMessage }, { status: 500 });
}

Expand Down
9 changes: 9 additions & 0 deletions app/services/models.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { db } from "~/utils/db.server";
import type { User } from "@supabase/supabase-js";
import { split } from "lodash";
import { sub } from "date-fns";

interface getModelsType {
limit?: number;
Expand All @@ -14,6 +15,7 @@ interface getModelsType {
profileId?: string | null | undefined;
tags?: string | null | undefined;
following?: boolean;
lastNDays?: number;
}

export const getModels = async (params: getModelsType) => {
Expand Down Expand Up @@ -124,6 +126,13 @@ export const getModels = async (params: getModelsType) => {
},
}),
...(params.following && followingQuery),
...(params.lastNDays
? {
createdAt: {
gte: sub(Date.now(), { days: params.lastNDays }),
},
}
: undefined),
},
select: {
_count: {
Expand Down
5 changes: 5 additions & 0 deletions app/utils/username.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const blockList = ["trending", "all", "popular", "tonehunt", "delete" /* TODO: add more words here */];

export const isNotAllowed = (username: string) => {
return blockList.includes(username);
};
Loading

0 comments on commit 9235317

Please sign in to comment.