File size: 2,602 Bytes
cd6f98e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import type { SyntheticEvent } from "react";
import { z } from "zod";

import { env } from "../../env/client.mjs";
import FadeIn from "../motions/FadeIn";

interface LinkInfo {
  link: string;
  index: number;
}

const MetaDataSchema = z.object({
  title: z.string().nullish(),
  favicon: z.string().nullish(),
  hostname: z.string().nullish(),
});

const SourceLink = ({ link, index }: LinkInfo) => {
  const linkMeta = useQuery(["linkMeta", link], async () =>
    MetaDataSchema.parse(
      (
        await axios.get(env.NEXT_PUBLIC_BACKEND_URL + "/api/metadata", {
          params: {
            url: link,
          },
        })
      ).data
    )
  );

  const addImageFallback = (event: SyntheticEvent<HTMLImageElement, Event>) => {
    event.currentTarget.src = "/errorFavicon.ico";
  };

  return (
    <FadeIn>
      <a href={link} target="_blank">
        <div className="group h-full space-y-2 rounded-lg border border-slate-8 bg-slate-3 p-2 transition-colors duration-300 hover:bg-slate-4">
          {linkMeta.isLoading ? (
            <div className="animate-pulse space-y-2">
              <div className="h-2 rounded bg-slate-8"></div>
              <div className="h-2 rounded bg-slate-8"></div>
              <div className="flex items-center gap-2">
                <div className="h-4 w-4 rounded bg-slate-8"></div>
                <div className="h-2 w-2/3  rounded bg-slate-8"></div>
              </div>
            </div>
          ) : linkMeta.isSuccess ? (
            <>
              <p className="line-clamp-2 text-xs">{linkMeta.data.title}</p>
              <div className="flex items-center gap-2 overflow-ellipsis">
                <img
                  className="inline h-4 w-4"
                  src={linkMeta.data.favicon || ""}
                  alt="Logo"
                  onError={addImageFallback}
                />
                <p className="line-clamp-1 overflow-ellipsis">{linkMeta.data.hostname}</p>
                <p className="rounded-full bg-slate-5 px-2 text-slate-12 transition-colors duration-300 group-hover:bg-sky-600 group-hover:text-white">
                  {index + 1}
                </p>
              </div>
            </>
          ) : linkMeta.isError ? (
            <div className="flex gap-2">
              <p className="line-clamp-1">{link}</p>
              <p className="rounded-full bg-slate-5 px-3 text-slate-12">{index + 1}</p>
            </div>
          ) : null}
        </div>
      </a>
    </FadeIn>
  );
};

export default SourceLink;