ServerCard.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import Image from "next/image"
  2. import { FormattedMessage, useIntl } from "react-intl"
  3. import { Blurhash } from "react-blurhash"
  4. import LinkButton from "./LinkButton"
  5. import type { Server } from "../types/api"
  6. import { categoriesMessages } from "../data/categories"
  7. import { formatNumber } from "../utils/numbers"
  8. import SkeletonText from "./SkeletonText"
  9. /**
  10. * Individual Server cards.
  11. * Omitting server prop renders a skeleton.
  12. */
  13. const ServerCard = ({ server }: { server?: Server }) => {
  14. const intl = useIntl()
  15. return (
  16. <div className="grid grid-rows-[auto_1fr_auto] rounded-md border border-gray-3 p-4">
  17. <div className="relative h-26 lg:h-40 rounded-md overflow-hidden bg-gray-2">
  18. {server ? (
  19. <>
  20. {server.blurhash && <Blurhash hash={server.blurhash} width='100%' height='100%' />}
  21. <Image
  22. src={server.proxied_thumbnail}
  23. layout="fill"
  24. objectFit="cover"
  25. alt=""
  26. unoptimized
  27. />
  28. </>
  29. ) : (
  30. <div className="h-full w-full rounded-md bg-gray-3" />
  31. )}
  32. </div>
  33. <div className="pb-5">
  34. <p className="b4 mt-4 mb-2 !font-semibold uppercase text-gray-2">
  35. {server ? (
  36. <>
  37. <span>
  38. {server.category in categoriesMessages
  39. ? intl.formatMessage(categoriesMessages[server.category])
  40. : server.category}
  41. </span>
  42. {server?.approval_required && (
  43. <span className="before:px-1 before:content-['·']">
  44. <FormattedMessage
  45. id="servers.approval_required"
  46. defaultMessage="Sign-ups reviewed manually"
  47. />
  48. </span>
  49. )}
  50. </>
  51. ) : (
  52. <SkeletonText className="w-[16ch]" />
  53. )}
  54. </p>
  55. <p className="b1 !font-700 mb-2">
  56. {server ? server.domain : <SkeletonText className="w-[14ch]" />}
  57. </p>
  58. <p className="b3 line-clamp-5 [unicode-bidi:plaintext]">
  59. {server ? (
  60. server.description
  61. ) : (
  62. <>
  63. <SkeletonText className="w-[27ch]" />
  64. <SkeletonText className="w-[26ch]" />
  65. <SkeletonText className="w-[12ch]" />
  66. </>
  67. )}
  68. </p>
  69. </div>
  70. <div className="">
  71. {server ? (
  72. <LinkButton
  73. href={`https://${server.domain}/auth/sign_up`}
  74. light={server.approval_required}
  75. fullWidth
  76. size="small"
  77. >
  78. {server.approval_required ? (
  79. <FormattedMessage
  80. id="servers.apply_for_an_account"
  81. defaultMessage="Apply for an account"
  82. />
  83. ) : (
  84. <FormattedMessage
  85. id="servers.create_account"
  86. defaultMessage="Create account"
  87. />
  88. )}
  89. </LinkButton>
  90. ) : (
  91. <div className="flex h-10 rounded border-2 border-gray-3" />
  92. )}
  93. </div>
  94. </div>
  95. )
  96. }
  97. export default ServerCard