๐Ÿ“ฆ hyoban / kodoku

๐Ÿ“„ page.tsx ยท 84 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84import Image from 'next/image'
import { Suspense } from 'react'

import { IconLink } from '~/components/icon-link'
import { Link } from '~/components/link'
import { Loading } from '~/components/loading'
import { NewFeedDialog } from '~/components/new-feed'
import { Avatar, AvatarFallback, AvatarImage } from '~/components/ui/avatar'
import { Separator } from '~/components/ui/separator'
import { env } from '~/env'
import { getFeedInfoList } from '~/lib/unsafe'

export const revalidate = 3600

async function FeedInfoList() {
  const feedInfoList = await getFeedInfoList()

  return (
    <>
      <NewFeedDialog
        existingFeedUrls={feedInfoList
          .map(feedInfo => feedInfo.feedUrl)
          .filter(Boolean)}
      />
      {feedInfoList
        .sort((a, b) =>
          env.NODE_ENV === 'development'
            ? a.title.localeCompare(b.title)
            : Math.random() - 0.5,
        )
        .map(feedInfo => (
          <div
            key={feedInfo.id}
            className="group w-full mx-auto my-4 flex items-center rounded-md px-4 py-3 hover:bg-accent"
          >
            <Avatar>
              <AvatarImage asChild src={feedInfo.avatar ?? ''}>
                <Image
                  src={feedInfo.avatar ?? ''}
                  className="size-12 shrink-0 grow-0 rounded-full bg-white object-cover"
                  alt="avatar"
                  width={48}
                  height={48}
                />
              </AvatarImage>
              <AvatarFallback>
                {feedInfo.title.slice(0, 2).toUpperCase()}
              </AvatarFallback>
            </Avatar>
            <div className="ml-4 flex w-full flex-col self-stretch">
              <div className="flex grow flex-col sm:flex-row sm:items-center sm:justify-between">
                {feedInfo.url
                  ? (
                    <Link href={feedInfo.url} className="flex items-center">
                      <h3 className="text-lg font-semibold">{feedInfo.title}</h3>
                    </Link>
                    )
                  : (
                    <h3 className="text-lg font-semibold">{feedInfo.title}</h3>
                    )}
                <span className="my-2 flex gap-3">
                  {feedInfo.socials.filter(Boolean).map(link => (
                    <IconLink key={link} link={link} />
                  ))}
                </span>
              </div>
              <Separator className="group-hover:bg-accent" />
            </div>
          </div>
        ))}
    </>
  )
}

export default function Page() {
  return (
    <div className="m-5 sm:m-10 self-center md:min-w-[30rem] flex flex-col">
      <Suspense fallback={<Loading />}>
        <FeedInfoList />
      </Suspense>
    </div>
  )
}