Refine CRUD for artists
This commit is contained in:
		
							
								
								
									
										10
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -23,6 +23,7 @@
 | 
			
		||||
        "react": "^19.0.0",
 | 
			
		||||
        "react-dom": "^19.0.0",
 | 
			
		||||
        "react-hook-form": "^7.58.1",
 | 
			
		||||
        "react-icons": "^5.5.0",
 | 
			
		||||
        "sonner": "^2.0.5",
 | 
			
		||||
        "tailwind-merge": "^3.3.1",
 | 
			
		||||
        "zod": "^3.25.67"
 | 
			
		||||
@ -6154,6 +6155,15 @@
 | 
			
		||||
        "react": "^16.8.0 || ^17 || ^18 || ^19"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/react-icons": {
 | 
			
		||||
      "version": "5.5.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
 | 
			
		||||
      "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "react": "*"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/react-is": {
 | 
			
		||||
      "version": "16.13.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
 | 
			
		||||
 | 
			
		||||
@ -24,6 +24,7 @@
 | 
			
		||||
    "react": "^19.0.0",
 | 
			
		||||
    "react-dom": "^19.0.0",
 | 
			
		||||
    "react-hook-form": "^7.58.1",
 | 
			
		||||
    "react-icons": "^5.5.0",
 | 
			
		||||
    "sonner": "^2.0.5",
 | 
			
		||||
    "tailwind-merge": "^3.3.1",
 | 
			
		||||
    "zod": "^3.25.67"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										21
									
								
								prisma/migrations/20250625130123_artist_social/migration.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								prisma/migrations/20250625130123_artist_social/migration.sql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
/*
 | 
			
		||||
  Warnings:
 | 
			
		||||
 | 
			
		||||
  - You are about to drop the column `icon` on the `Social` table. All the data in the column will be lost.
 | 
			
		||||
  - You are about to drop the column `name` on the `Social` table. All the data in the column will be lost.
 | 
			
		||||
  - You are about to drop the column `type` on the `Social` table. All the data in the column will be lost.
 | 
			
		||||
  - You are about to drop the column `url` on the `Social` table. All the data in the column will be lost.
 | 
			
		||||
  - Added the required column `isPrimary` to the `Social` table without a default value. This is not possible if the table is not empty.
 | 
			
		||||
  - Added the required column `platform` to the `Social` table without a default value. This is not possible if the table is not empty.
 | 
			
		||||
  - Made the column `handle` on table `Social` required. This step will fail if there are existing NULL values in that column.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
-- AlterTable
 | 
			
		||||
ALTER TABLE "Social" DROP COLUMN "icon",
 | 
			
		||||
DROP COLUMN "name",
 | 
			
		||||
DROP COLUMN "type",
 | 
			
		||||
DROP COLUMN "url",
 | 
			
		||||
ADD COLUMN     "isPrimary" BOOLEAN NOT NULL,
 | 
			
		||||
ADD COLUMN     "link" TEXT,
 | 
			
		||||
ADD COLUMN     "platform" TEXT NOT NULL,
 | 
			
		||||
ALTER COLUMN "handle" SET NOT NULL;
 | 
			
		||||
@ -70,11 +70,11 @@ model Social {
 | 
			
		||||
  createdAt DateTime @default(now())
 | 
			
		||||
  updatedAt DateTime @updatedAt
 | 
			
		||||
 | 
			
		||||
  name   String?
 | 
			
		||||
  handle String?
 | 
			
		||||
  url    String?
 | 
			
		||||
  type   String?
 | 
			
		||||
  icon   String?
 | 
			
		||||
  platform  String
 | 
			
		||||
  handle    String
 | 
			
		||||
  isPrimary Boolean
 | 
			
		||||
 | 
			
		||||
  link String?
 | 
			
		||||
 | 
			
		||||
  artistId String?
 | 
			
		||||
  artist   Artist? @relation(fields: [artistId], references: [id])
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,15 @@ export async function createArtist(values: z.infer<typeof artistSchema>) {
 | 
			
		||||
    data: {
 | 
			
		||||
      displayName: values.displayName,
 | 
			
		||||
      slug: values.slug,
 | 
			
		||||
      nickname: values.nickname
 | 
			
		||||
      nickname: values.nickname,
 | 
			
		||||
      socials: {
 | 
			
		||||
        create: (values.socials || []).map((s) => ({
 | 
			
		||||
          platform: s.platform,
 | 
			
		||||
          handle: s.handle,
 | 
			
		||||
          link: s.link,
 | 
			
		||||
          isPrimary: s.isPrimary,
 | 
			
		||||
        })),
 | 
			
		||||
      },
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
@ -8,6 +8,16 @@ export async function updateArtist(
 | 
			
		||||
  values: z.infer<typeof artistSchema>, 
 | 
			
		||||
  id: string
 | 
			
		||||
) {
 | 
			
		||||
  const existingSocials = await prisma.social.findMany({
 | 
			
		||||
    where: { artistId: id },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const updatedSocialIds = (values.socials ?? []).filter(s => s.id).map(s => s.id);
 | 
			
		||||
 | 
			
		||||
  const removedSocials = existingSocials.filter(
 | 
			
		||||
    (s) => !updatedSocialIds.includes(s.id)
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return await prisma.artist.update({
 | 
			
		||||
    where: {
 | 
			
		||||
      id: id
 | 
			
		||||
@ -15,7 +25,31 @@ export async function updateArtist(
 | 
			
		||||
    data: {
 | 
			
		||||
      displayName: values.displayName,
 | 
			
		||||
      slug: values.slug,
 | 
			
		||||
      nickname: values.nickname
 | 
			
		||||
      nickname: values.nickname,
 | 
			
		||||
      socials: {
 | 
			
		||||
        deleteMany: {
 | 
			
		||||
          id: { in: removedSocials.map(s => s.id) },
 | 
			
		||||
        },
 | 
			
		||||
        updateMany: (values.socials ?? [])
 | 
			
		||||
          .filter((s) => s.id)
 | 
			
		||||
          .map((s) => ({
 | 
			
		||||
            where: { id: s.id },
 | 
			
		||||
            data: {
 | 
			
		||||
              platform: s.platform,
 | 
			
		||||
              handle: s.handle,
 | 
			
		||||
              link: s.link,
 | 
			
		||||
              isPrimary: s.isPrimary,
 | 
			
		||||
            },
 | 
			
		||||
          })),
 | 
			
		||||
        create: (values.socials ?? [])
 | 
			
		||||
          .filter((s) => !s.id)
 | 
			
		||||
          .map((s) => ({
 | 
			
		||||
            platform: s.platform,
 | 
			
		||||
            handle: s.handle,
 | 
			
		||||
            link: s.link,
 | 
			
		||||
            isPrimary: s.isPrimary,
 | 
			
		||||
          })),
 | 
			
		||||
      },
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
@ -7,6 +7,9 @@ export default async function ArtistsEditPage({ params }: { params: { id: string
 | 
			
		||||
  const artist = await prisma.artist.findUnique({
 | 
			
		||||
    where: {
 | 
			
		||||
      id,
 | 
			
		||||
    },
 | 
			
		||||
    include: {
 | 
			
		||||
      socials: true
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,15 +4,16 @@ import { updateArtist } from "@/actions/artists/updateArtist";
 | 
			
		||||
import { Button } from "@/components/ui/button";
 | 
			
		||||
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
 | 
			
		||||
import { Input } from "@/components/ui/input";
 | 
			
		||||
import { Artist } from "@/generated/prisma";
 | 
			
		||||
import { Artist, Social } from "@/generated/prisma";
 | 
			
		||||
import { artistSchema } from "@/schemas/artists/artistSchema";
 | 
			
		||||
import { getSocialIcon } from "@/utils/socialIconMap";
 | 
			
		||||
import { zodResolver } from "@hookform/resolvers/zod";
 | 
			
		||||
import { useRouter } from "next/navigation";
 | 
			
		||||
import { useForm } from "react-hook-form";
 | 
			
		||||
import { useFieldArray, useForm } from "react-hook-form";
 | 
			
		||||
import { toast } from "sonner";
 | 
			
		||||
import * as z from "zod/v4";
 | 
			
		||||
 | 
			
		||||
export default function EditAlbumForm({ artist }: { artist: Artist }) {
 | 
			
		||||
export default function EditAlbumForm({ artist }: { artist: Artist & { socials: Social[] } }) {
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
  const form = useForm<z.infer<typeof artistSchema>>({
 | 
			
		||||
    resolver: zodResolver(artistSchema),
 | 
			
		||||
@ -20,9 +21,23 @@ export default function EditAlbumForm({ artist }: { artist: Artist }) {
 | 
			
		||||
      displayName: artist.displayName,
 | 
			
		||||
      slug: artist.slug,
 | 
			
		||||
      nickname: artist.nickname || "",
 | 
			
		||||
      socials: artist.socials.map((s) => ({
 | 
			
		||||
        id: s.id,
 | 
			
		||||
        platform: s.platform,
 | 
			
		||||
        handle: s.handle,
 | 
			
		||||
        link: s.link ?? "",  // Convert null to empty string
 | 
			
		||||
        isPrimary: s.isPrimary,
 | 
			
		||||
      })),
 | 
			
		||||
    },
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const { fields, append, remove } = useFieldArray({
 | 
			
		||||
    control: form.control,
 | 
			
		||||
    name: "socials",
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const watchSocials = form.watch("socials");
 | 
			
		||||
 | 
			
		||||
  async function onSubmit(values: z.infer<typeof artistSchema>) {
 | 
			
		||||
    const updatedArtist = await updateArtist(values, artist.id)
 | 
			
		||||
    if (updatedArtist) {
 | 
			
		||||
@ -83,6 +98,95 @@ export default function EditAlbumForm({ artist }: { artist: Artist }) {
 | 
			
		||||
              </FormItem>
 | 
			
		||||
            )}
 | 
			
		||||
          />
 | 
			
		||||
 | 
			
		||||
          {/* Socials section */}
 | 
			
		||||
          <div className="space-y-4">
 | 
			
		||||
            <FormLabel>Social Links</FormLabel>
 | 
			
		||||
            {fields.map((field, index) => (
 | 
			
		||||
              <div key={field.id} className="flex flex-col gap-2 border rounded p-4">
 | 
			
		||||
                <div className="flex items-center gap-2">
 | 
			
		||||
                  {getSocialIcon(watchSocials?.[index]?.platform ?? "")}
 | 
			
		||||
                  <FormField
 | 
			
		||||
                    control={form.control}
 | 
			
		||||
                    name={`socials.${index}.platform`}
 | 
			
		||||
                    render={({ field }) => (
 | 
			
		||||
                      <FormItem className="w-full">
 | 
			
		||||
                        <FormLabel>Platform</FormLabel>
 | 
			
		||||
                        <FormControl>
 | 
			
		||||
                          <Input placeholder="e.g. telegram" {...field} />
 | 
			
		||||
                        </FormControl>
 | 
			
		||||
                        <FormMessage />
 | 
			
		||||
                      </FormItem>
 | 
			
		||||
                    )}
 | 
			
		||||
                  />
 | 
			
		||||
                </div>
 | 
			
		||||
                <FormField
 | 
			
		||||
                  control={form.control}
 | 
			
		||||
                  name={`socials.${index}.handle`}
 | 
			
		||||
                  render={({ field }) => (
 | 
			
		||||
                    <FormItem>
 | 
			
		||||
                      <FormLabel>Handle</FormLabel>
 | 
			
		||||
                      <FormControl>
 | 
			
		||||
                        <Input placeholder="@username" {...field} />
 | 
			
		||||
                      </FormControl>
 | 
			
		||||
                      <FormMessage />
 | 
			
		||||
                    </FormItem>
 | 
			
		||||
                  )}
 | 
			
		||||
                />
 | 
			
		||||
                <FormField
 | 
			
		||||
                  control={form.control}
 | 
			
		||||
                  name={`socials.${index}.link`}
 | 
			
		||||
                  render={({ field }) => (
 | 
			
		||||
                    <FormItem>
 | 
			
		||||
                      <FormLabel>Link</FormLabel>
 | 
			
		||||
                      <FormControl>
 | 
			
		||||
                        <Input placeholder="https://example.com/username" {...field} />
 | 
			
		||||
                      </FormControl>
 | 
			
		||||
                      <FormMessage />
 | 
			
		||||
                    </FormItem>
 | 
			
		||||
                  )}
 | 
			
		||||
                />
 | 
			
		||||
                <FormField
 | 
			
		||||
                  control={form.control}
 | 
			
		||||
                  name={`socials.${index}.isPrimary`}
 | 
			
		||||
                  render={({ field }) => (
 | 
			
		||||
                    <FormItem className="flex items-center gap-2">
 | 
			
		||||
                      <input
 | 
			
		||||
                        type="radio"
 | 
			
		||||
                        checked={field.value}
 | 
			
		||||
                        onChange={
 | 
			
		||||
                          () =>
 | 
			
		||||
                            form.setValue(
 | 
			
		||||
                              "socials",
 | 
			
		||||
                              (watchSocials ?? []).map((s, i) => ({
 | 
			
		||||
                                ...s,
 | 
			
		||||
                                isPrimary: i === index,
 | 
			
		||||
                              }))
 | 
			
		||||
                            )
 | 
			
		||||
                        }
 | 
			
		||||
                      />
 | 
			
		||||
                      <FormLabel className="m-0 text-sm">Set as primary</FormLabel>
 | 
			
		||||
                    </FormItem>
 | 
			
		||||
                  )}
 | 
			
		||||
                />
 | 
			
		||||
                <Button
 | 
			
		||||
                  type="button"
 | 
			
		||||
                  variant="ghost"
 | 
			
		||||
                  onClick={() => remove(index)}
 | 
			
		||||
                >
 | 
			
		||||
                  Remove Social
 | 
			
		||||
                </Button>
 | 
			
		||||
              </div>
 | 
			
		||||
            ))}
 | 
			
		||||
            <Button
 | 
			
		||||
              type="button"
 | 
			
		||||
              variant="outline"
 | 
			
		||||
              onClick={() => append({ platform: "", handle: "", link: "", isPrimary: false })}
 | 
			
		||||
            >
 | 
			
		||||
              + Add Social
 | 
			
		||||
            </Button>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <div className="flex flex-col gap-4">
 | 
			
		||||
            <Button type="submit">Submit</Button>
 | 
			
		||||
            <Button type="reset" variant="secondary" onClick={() => router.back()}>Cancel</Button>
 | 
			
		||||
 | 
			
		||||
@ -5,9 +5,10 @@ import { Button } from "@/components/ui/button";
 | 
			
		||||
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
 | 
			
		||||
import { Input } from "@/components/ui/input";
 | 
			
		||||
import { artistSchema } from "@/schemas/artists/artistSchema";
 | 
			
		||||
import { getSocialIcon } from "@/utils/socialIconMap";
 | 
			
		||||
import { zodResolver } from "@hookform/resolvers/zod";
 | 
			
		||||
import { useRouter } from "next/navigation";
 | 
			
		||||
import { useForm } from "react-hook-form";
 | 
			
		||||
import { useFieldArray, useForm } from "react-hook-form";
 | 
			
		||||
import { toast } from "sonner";
 | 
			
		||||
import * as z from "zod/v4";
 | 
			
		||||
 | 
			
		||||
@ -19,9 +20,17 @@ export default function CreateArtistForm() {
 | 
			
		||||
      displayName: "",
 | 
			
		||||
      slug: "",
 | 
			
		||||
      nickname: "",
 | 
			
		||||
      socials: [],
 | 
			
		||||
    },
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const { fields, append, remove } = useFieldArray({
 | 
			
		||||
    control: form.control,
 | 
			
		||||
    name: "socials",
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const watchSocials = form.watch("socials");
 | 
			
		||||
 | 
			
		||||
  async function onSubmit(values: z.infer<typeof artistSchema>) {
 | 
			
		||||
    const artist = await createArtist(values)
 | 
			
		||||
    if (artist) {
 | 
			
		||||
@ -81,6 +90,95 @@ export default function CreateArtistForm() {
 | 
			
		||||
            </FormItem>
 | 
			
		||||
          )}
 | 
			
		||||
        />
 | 
			
		||||
 | 
			
		||||
        {/* Socials section */}
 | 
			
		||||
        <div className="space-y-4">
 | 
			
		||||
          <FormLabel>Social Links</FormLabel>
 | 
			
		||||
          {fields.map((field, index) => (
 | 
			
		||||
            <div key={field.id} className="flex flex-col gap-2 border rounded p-4">
 | 
			
		||||
              <div className="flex items-center gap-2">
 | 
			
		||||
                {getSocialIcon(watchSocials?.[index]?.platform ?? "")}
 | 
			
		||||
                <FormField
 | 
			
		||||
                  control={form.control}
 | 
			
		||||
                  name={`socials.${index}.platform`}
 | 
			
		||||
                  render={({ field }) => (
 | 
			
		||||
                    <FormItem className="w-full">
 | 
			
		||||
                      <FormLabel>Platform</FormLabel>
 | 
			
		||||
                      <FormControl>
 | 
			
		||||
                        <Input placeholder="e.g. telegram" {...field} />
 | 
			
		||||
                      </FormControl>
 | 
			
		||||
                      <FormMessage />
 | 
			
		||||
                    </FormItem>
 | 
			
		||||
                  )}
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
              <FormField
 | 
			
		||||
                control={form.control}
 | 
			
		||||
                name={`socials.${index}.handle`}
 | 
			
		||||
                render={({ field }) => (
 | 
			
		||||
                  <FormItem>
 | 
			
		||||
                    <FormLabel>Handle</FormLabel>
 | 
			
		||||
                    <FormControl>
 | 
			
		||||
                      <Input placeholder="@username" {...field} />
 | 
			
		||||
                    </FormControl>
 | 
			
		||||
                    <FormMessage />
 | 
			
		||||
                  </FormItem>
 | 
			
		||||
                )}
 | 
			
		||||
              />
 | 
			
		||||
              <FormField
 | 
			
		||||
                control={form.control}
 | 
			
		||||
                name={`socials.${index}.link`}
 | 
			
		||||
                render={({ field }) => (
 | 
			
		||||
                  <FormItem>
 | 
			
		||||
                    <FormLabel>Link</FormLabel>
 | 
			
		||||
                    <FormControl>
 | 
			
		||||
                      <Input placeholder="https://example.com/username" {...field} />
 | 
			
		||||
                    </FormControl>
 | 
			
		||||
                    <FormMessage />
 | 
			
		||||
                  </FormItem>
 | 
			
		||||
                )}
 | 
			
		||||
              />
 | 
			
		||||
              <FormField
 | 
			
		||||
                control={form.control}
 | 
			
		||||
                name={`socials.${index}.isPrimary`}
 | 
			
		||||
                render={({ field }) => (
 | 
			
		||||
                  <FormItem className="flex items-center gap-2">
 | 
			
		||||
                    <input
 | 
			
		||||
                      type="radio"
 | 
			
		||||
                      checked={field.value}
 | 
			
		||||
                      onChange={
 | 
			
		||||
                        () =>
 | 
			
		||||
                          form.setValue(
 | 
			
		||||
                            "socials",
 | 
			
		||||
                            (watchSocials ?? []).map((s, i) => ({
 | 
			
		||||
                              ...s,
 | 
			
		||||
                              isPrimary: i === index,
 | 
			
		||||
                            }))
 | 
			
		||||
                          )
 | 
			
		||||
                      }
 | 
			
		||||
                    />
 | 
			
		||||
                    <FormLabel className="m-0 text-sm">Set as primary</FormLabel>
 | 
			
		||||
                  </FormItem>
 | 
			
		||||
                )}
 | 
			
		||||
              />
 | 
			
		||||
              <Button
 | 
			
		||||
                type="button"
 | 
			
		||||
                variant="ghost"
 | 
			
		||||
                onClick={() => remove(index)}
 | 
			
		||||
              >
 | 
			
		||||
                Remove Social
 | 
			
		||||
              </Button>
 | 
			
		||||
            </div>
 | 
			
		||||
          ))}
 | 
			
		||||
          <Button
 | 
			
		||||
            type="button"
 | 
			
		||||
            variant="outline"
 | 
			
		||||
            onClick={() => append({ platform: "", handle: "", link: "", isPrimary: false })}
 | 
			
		||||
          >
 | 
			
		||||
            + Add Social
 | 
			
		||||
          </Button>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div className="flex flex-col gap-4">
 | 
			
		||||
          <Button type="submit">Submit</Button>
 | 
			
		||||
          <Button type="reset" variant="secondary" onClick={() => router.back()}>Cancel</Button>
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,25 @@
 | 
			
		||||
import * as z from "zod/v4";
 | 
			
		||||
 | 
			
		||||
export const socialSchema = z.object({
 | 
			
		||||
  id: z.string().optional(),
 | 
			
		||||
  platform: z.string().min(1, "Platform is required"),
 | 
			
		||||
  handle: z.string().min(1, "Handle is required"),
 | 
			
		||||
  isPrimary: z.boolean(),
 | 
			
		||||
  link: z.string().optional(),
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export const artistSchema = z.object({
 | 
			
		||||
  displayName: z.string().min(3, "Name is required. Min 3 characters."),
 | 
			
		||||
  slug: z.string().min(3, "Slug is required. Min 3 characters.").regex(/^[a-z]+$/, "Only lowercase letters are allowed (no numbers, spaces, or uppercase)"),
 | 
			
		||||
  nickname: z.string().optional(),
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
  socials: z.array(socialSchema).optional(),
 | 
			
		||||
}).refine(
 | 
			
		||||
  (data) => {
 | 
			
		||||
    const socials = data.socials || [];
 | 
			
		||||
    return socials.filter((s) => s.isPrimary).length <= 1;
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    message: "Only one social can be primary",
 | 
			
		||||
    path: ["socials"],
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								src/utils/socialIconMap.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/utils/socialIconMap.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
import { FaGlobe, FaLink, FaMastodon, FaTelegram } from "react-icons/fa";
 | 
			
		||||
 | 
			
		||||
export const getSocialIcon = (platform: string) => {
 | 
			
		||||
  switch (platform.toLowerCase()) {
 | 
			
		||||
    case "telegram":
 | 
			
		||||
      return <FaTelegram className="text-sky-500" />;
 | 
			
		||||
    case "linktree":
 | 
			
		||||
      return <FaLink className="text-green-600" />;
 | 
			
		||||
    case "fediverse":
 | 
			
		||||
      return <FaMastodon className="text-indigo-500" />;
 | 
			
		||||
    default:
 | 
			
		||||
      return <FaGlobe className="text-muted-foreground" />;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user