mirror of
https://github.com/Hackdex-App/hackdex-website.git
synced 2026-06-20 22:29:47 -05:00
Add ability for admins to contact creators
This commit is contained in:
parent
e122a182d7
commit
ac81e2eebb
|
|
@ -43,6 +43,7 @@ export interface HackMetadata {
|
|||
username: string | null;
|
||||
avatar_url: string | null;
|
||||
verified: boolean;
|
||||
email: string | null;
|
||||
} | null;
|
||||
otherHacks: {
|
||||
slug: string;
|
||||
|
|
@ -104,10 +105,17 @@ export async function getHackMetadata(slug: string): Promise<HackMetadata | null
|
|||
// Fetch profile
|
||||
const { data: profile } = await supabase
|
||||
.from("profiles")
|
||||
.select("username,avatar_url,verified")
|
||||
.select("id,username,avatar_url,verified")
|
||||
.eq("id", hack.created_by as string)
|
||||
.maybeSingle();
|
||||
|
||||
// Meant to only be available to admins (gated in server-side page rendering)
|
||||
let userEmail: string | null = null;
|
||||
if (profile) {
|
||||
const { data: userData } = await supabase.auth.admin.getUserById(profile.id);
|
||||
userEmail = userData?.user?.email || null;
|
||||
}
|
||||
|
||||
// Get other approved hacks by the same author (non-archive hacks only)
|
||||
let otherHacks: {
|
||||
slug: string;
|
||||
|
|
@ -160,6 +168,7 @@ export async function getHackMetadata(slug: string): Promise<HackMetadata | null
|
|||
username: profile.username,
|
||||
avatar_url: profile.avatar_url,
|
||||
verified: profile.verified,
|
||||
email: userEmail,
|
||||
} : null,
|
||||
otherHacks,
|
||||
patch,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import HackActions from "@/components/Hack/HackActions";
|
|||
import Markdown from "@/components/Markdown/Markdown";
|
||||
import Image from "next/image";
|
||||
import { FaDiscord, FaTwitter, FaGithub, FaTriangleExclamation, FaArrowUpRightFromSquare } from "react-icons/fa6";
|
||||
import { FiAlertTriangle, FiInfo } from "react-icons/fi";
|
||||
import { FiAlertTriangle, FiInfo, FiMail } from "react-icons/fi";
|
||||
import PokeCommunityIcon from "@/components/Icons/PokeCommunityIcon";
|
||||
import { createClient, createServiceClient } from "@/utils/supabase/server";
|
||||
import HackOptionsMenu from "@/components/Hack/HackOptionsMenu";
|
||||
|
|
@ -134,18 +134,15 @@ export default async function HackDetail({ params }: HackDetailProps) {
|
|||
canEdit: canUploadPatch,
|
||||
} = await checkPatchEditPermission(hack, user?.id as string, supabase);
|
||||
|
||||
// isAdmin always needs to be checked for archive hacks
|
||||
let isAdmin = false;
|
||||
if (!hack.approved || isArchive) {
|
||||
const { data: admin } = await supabase.rpc("is_admin");
|
||||
if (admin) {
|
||||
isAdmin = true;
|
||||
} else if (!hack.approved) {
|
||||
if (isArchive && !canEditAsArchiver) {
|
||||
return notFound();
|
||||
} else if (!canEdit) {
|
||||
return notFound();
|
||||
}
|
||||
const { data: admin } = await supabase.rpc("is_admin");
|
||||
if (admin) {
|
||||
isAdmin = true;
|
||||
} else if (!hack.approved || isArchive) {
|
||||
if (isArchive && !canEditAsArchiver) {
|
||||
return notFound();
|
||||
} else if (!canEdit) {
|
||||
return notFound();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -452,6 +449,16 @@ export default async function HackDetail({ params }: HackDetailProps) {
|
|||
Approve
|
||||
</MenuItem>
|
||||
)}
|
||||
{isAdmin && profile?.email && (
|
||||
<MenuItem
|
||||
as="a"
|
||||
href={`mailto:${profile.email}`}
|
||||
className="block w-full px-3 py-2 text-left text-sm text-foreground/80 font-medium data-focus:bg-black/5 dark:data-focus:bg-white/10"
|
||||
>
|
||||
<FiMail className="mr-2 inline-block align-middle mb-0.5 text-foreground/80" size={12} />
|
||||
Contact creator
|
||||
</MenuItem>
|
||||
)}
|
||||
</HackOptionsMenu>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { FiMoreVertical, FiEdit2, FiBarChart2 } from "react-icons/fi";
|
||||
import { TbVersions } from "react-icons/tb";
|
||||
import { Menu, MenuButton, MenuItem, MenuItems, MenuSeparator } from "@headlessui/react";
|
||||
|
|
@ -21,6 +21,10 @@ export default function HackOptionsMenu({
|
|||
}: HackOptionsMenuProps) {
|
||||
const [showReportModal, setShowReportModal] = useState(false);
|
||||
|
||||
const hasRenderableChildren = useMemo(() => {
|
||||
return React.Children.toArray(children).some(Boolean);
|
||||
}, [children]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Menu as="div" className="relative">
|
||||
|
|
@ -91,7 +95,7 @@ export default function HackOptionsMenu({
|
|||
Manage versions
|
||||
</MenuItem>
|
||||
)}
|
||||
{children && <>
|
||||
{hasRenderableChildren && <>
|
||||
<MenuSeparator className="my-1 h-px bg-[var(--border)]" />
|
||||
{children}
|
||||
</>}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user