diff --git a/app/components/page-layout.tsx b/app/components/page-layout.tsx index 50d3048..6eaa191 100644 --- a/app/components/page-layout.tsx +++ b/app/components/page-layout.tsx @@ -47,13 +47,10 @@ export function PageLayout({ children }: PageLayoutProps) { Listen
  • - Music + Music
  • - Sports -
  • -
  • - News & Talk + News & Talk
  • Manage Content diff --git a/app/components/stations-gallery.tsx b/app/components/stations-gallery.tsx new file mode 100644 index 0000000..29103ea --- /dev/null +++ b/app/components/stations-gallery.tsx @@ -0,0 +1,37 @@ +import { Link } from "@remix-run/react"; +import type { ConvertDatesToStrings } from "@remix-run/router/utils"; +import type { StationWithTags } from "~/models/station.server"; + +export type StationsGalleryProps = { + stations: ConvertDatesToStrings>[] +}; + +export function StationsGallery({ stations }: StationsGalleryProps) { + return ( +
    + {stations.map((station) => { + return ( +
    +
    Radio Station
    +
    +

    + {station.name} +

    +

    + {station.tags.map((t, id) => { + return {t.tag.name}; + })} +

    +

    {station.description}

    +
    + +
    +
    +
    + ); + + })} +
    + ); +} diff --git a/app/models/station.server.ts b/app/models/station.server.ts index a699950..219bdd5 100644 --- a/app/models/station.server.ts +++ b/app/models/station.server.ts @@ -1,4 +1,4 @@ -import type { PrismaClient, Station, Tag } from "@prisma/client"; +import type { Prisma, PrismaClient, Station, Tag } from "@prisma/client"; import { prisma } from "~/db.server"; import { upsertTagOnName } from "~/models/tag.server"; import { slugify } from "~/utils"; @@ -16,6 +16,43 @@ export type StationInput = { export type PrismaTxClient = Omit; +export function findStationsByTags(tags: string[]) { + return prisma.station.findMany({ + where: { + tags: { + some: { + tag: { + name: { in: tags } + } + } + } + }, + include: { + tags: { + include: { + tag: true + } + } + } + }); +} + +export type StationWithTags = Prisma.PromiseReturnType; + +export function getStationById(id: string) { + return prisma.station.findUnique({ + where: { id }, + include: { + tags: { + include: { + tag: true + } + } + } + }); + +} + export function upsertStationOnStreamUrl(input: StationInput, p: PrismaTxClient = prisma) { return p.station.upsert({ where: { streamUrl: input.streamUrl }, diff --git a/app/models/tag.server.ts b/app/models/tag.server.ts index b95142a..cb58cd6 100644 --- a/app/models/tag.server.ts +++ b/app/models/tag.server.ts @@ -2,6 +2,10 @@ import { prisma } from "~/db.server"; import type { PrismaTxClient } from "~/models/station.server"; import { slugify } from "~/utils"; +export function findTagBySlug(slug: string) { + return prisma.tag.findUnique({ where: { slug } }); +} + export function upsertTagOnName(tag: string, p: PrismaTxClient = prisma) { const slug = slugify(tag); return p.tag.upsert({ diff --git a/app/routes/listen._index.tsx b/app/routes/listen._index.tsx new file mode 100644 index 0000000..63509f6 --- /dev/null +++ b/app/routes/listen._index.tsx @@ -0,0 +1,13 @@ +import { Link } from "@remix-run/react"; +import { Breadcrumbs } from "~/components/breadcrumbs"; + +export default function ListenHome() { + return ( + <> + + Home + + + ); + +} diff --git a/app/routes/listen.channel.$channel.tsx b/app/routes/listen.channel.$channel.tsx new file mode 100644 index 0000000..fb35c8b --- /dev/null +++ b/app/routes/listen.channel.$channel.tsx @@ -0,0 +1,58 @@ +import type { LoaderArgs } from "@remix-run/node"; +import { json } from "@remix-run/node"; +import { Link, useLoaderData } from "@remix-run/react"; +import { Breadcrumbs } from "~/components/breadcrumbs"; +import { StationsGallery } from "~/components/stations-gallery"; +import type { StationWithTags } from "~/models/station.server"; +import { findStationsByTags } from "~/models/station.server"; +import { notFound } from "~/utils"; + + +export type Channel = { + tags: string[]; + slug: string; + name: string; +} + +const channels: { [channel: string]: Channel } = { + "music": { + tags: ["music"], + slug: "music", + name: "Music" + }, + "news": { + tags: ["news"], + slug: "news", + name: "News" + } +}; + + +export async function loader({ params }: LoaderArgs) { + if (!params.channel) { + throw notFound(); + } + + const channel = channels[params.channel]; + if (!channel) { + throw notFound(); + } + + const stations: NonNullable[] = await findStationsByTags(channel.tags); + return json({ channel, stations }); +} + +export default function ListenChannel() { + const { channel, stations } = useLoaderData(); + + return ( + <> + + Home + {channel.name} + + + + ); + +} diff --git a/app/routes/listen.tag.$tag.tsx b/app/routes/listen.tag.$tag.tsx new file mode 100644 index 0000000..13ae53b --- /dev/null +++ b/app/routes/listen.tag.$tag.tsx @@ -0,0 +1,40 @@ +import type { LoaderArgs } from "@remix-run/node"; +import { json } from "@remix-run/node"; +import { Link, useLoaderData } from "@remix-run/react"; +import { Breadcrumbs } from "~/components/breadcrumbs"; +import { StationsGallery } from "~/components/stations-gallery"; +import type { StationWithTags } from "~/models/station.server"; +import { findStationsByTags } from "~/models/station.server"; +import { findTagBySlug } from "~/models/tag.server"; +import { notFound } from "~/utils"; + + +export async function loader({ params }: LoaderArgs) { + if (!params.tag) { + throw notFound(); + } + + const tag = await findTagBySlug(params.tag); + if (!tag) { + throw notFound(); + } + + const stations: NonNullable[] = await findStationsByTags([tag.name]); + + return json({ tag, stations }); + + +} + +export default function ListenTag() { + const { tag, stations } = useLoaderData(); + return ( + <> + + Home + {tag.name} + + + + ); +} diff --git a/app/routes/listen.tsx b/app/routes/listen.tsx new file mode 100644 index 0000000..bce6b09 --- /dev/null +++ b/app/routes/listen.tsx @@ -0,0 +1,8 @@ +import { Outlet } from "@remix-run/react"; + + +export default function ListenLayout() { + return ( + + ); +}