mirror of
https://github.com/Hackdex-App/hackdex-website.git
synced 2026-03-21 17:54:09 -05:00
Add optional verification contact field
This commit is contained in:
parent
51f9eaa94b
commit
456832aad3
|
|
@ -30,6 +30,7 @@ export interface HackMetadata {
|
|||
language: string | null;
|
||||
is_archive: boolean;
|
||||
completion_status: Database["public"]["Enums"]["Completion Status"] | null;
|
||||
verification_contact_info: string | null;
|
||||
};
|
||||
images: string[];
|
||||
tags: string[];
|
||||
|
|
@ -59,12 +60,17 @@ export async function getHackMetadata(slug: string): Promise<HackMetadata | null
|
|||
|
||||
const { data: hack, error } = await supabase
|
||||
.from("hacks")
|
||||
.select("slug,title,summary,description,base_rom,created_at,updated_at,current_patch,box_art,social_links,created_by,approved,original_author,permission_from,language,is_archive,completion_status")
|
||||
.select("slug,title,summary,description,base_rom,created_at,updated_at,current_patch,box_art,social_links,created_by,approved,original_author,permission_from,language,is_archive,completion_status,verification_contact_info")
|
||||
.eq("slug", slug)
|
||||
.maybeSingle();
|
||||
|
||||
if (error || !hack) return null;
|
||||
|
||||
// Security: Don't return verification_contact_info if hack is approved
|
||||
if (hack.approved) {
|
||||
hack.verification_contact_info = null;
|
||||
}
|
||||
|
||||
// Fetch covers
|
||||
let images: string[] = [];
|
||||
const { data: covers } = await supabase
|
||||
|
|
|
|||
|
|
@ -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 } from "react-icons/fi";
|
||||
import { FiAlertTriangle, FiInfo } from "react-icons/fi";
|
||||
import PokeCommunityIcon from "@/components/Icons/PokeCommunityIcon";
|
||||
import { createClient, createServiceClient } from "@/utils/supabase/server";
|
||||
import HackOptionsMenu from "@/components/Hack/HackOptionsMenu";
|
||||
|
|
@ -360,6 +360,23 @@ export default async function HackDetail({ params }: HackDetailProps) {
|
|||
</div>
|
||||
)
|
||||
)}
|
||||
{isAdmin && hack.verification_contact_info && (
|
||||
<div className="mx-6 mt-6 rounded-lg border-2 border-blue-500/60 bg-blue-50 dark:bg-blue-900/20 p-4 md:pl-6">
|
||||
<div className="flex items-center gap-4 md:gap-6">
|
||||
<div className="flex-shrink-0">
|
||||
<FiInfo className="text-blue-600 dark:text-blue-400" size={24} />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-lg font-semibold text-blue-900 dark:text-blue-100 mb-2">
|
||||
Verification Contact Information
|
||||
</h3>
|
||||
<div className="text-sm text-blue-800 dark:text-blue-200 whitespace-pre-line">
|
||||
{hack.verification_contact_info}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ export async function prepareSubmission(formData: FormData) {
|
|||
const tags = (formData.get("tags") as string)?.split(",").map((t) => t.trim()).filter(Boolean) || [];
|
||||
const original_author = (formData.get("original_author") as string)?.trim() || null;
|
||||
const permission_from = (formData.get("permission_from") as string)?.trim() || null;
|
||||
const verification_contact_info = (formData.get("verification_contact_info") as string)?.trim() || null;
|
||||
const is_archive = formData.get("is_archive") === "true";
|
||||
|
||||
// For archives, version is not required; for regular hacks, it is
|
||||
|
|
@ -93,6 +94,7 @@ export async function prepareSubmission(formData: FormData) {
|
|||
patch_url: "",
|
||||
original_author: original_author || null,
|
||||
permission_from: permission_from || null,
|
||||
verification_contact_info: verification_contact_info || null,
|
||||
current_patch: null, // Archives don't have patches
|
||||
} as HackInsert;
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ export default function HackSubmitForm({
|
|||
const [twitter, setTwitter] = React.useState(() => initialDraftRef.current?.twitter || "");
|
||||
const [pokecommunity, setPokecommunity] = React.useState(() => initialDraftRef.current?.pokecommunity || "");
|
||||
const [github, setGithub] = React.useState(() => initialDraftRef.current?.github || "");
|
||||
const [verificationContactInfo, setVerificationContactInfo] = React.useState(() => initialDraftRef.current?.verificationContactInfo || "");
|
||||
const [tags, setTags] = React.useState<string[]>(() => (Array.isArray(initialDraftRef.current?.tags) ? initialDraftRef.current.tags : []));
|
||||
const [showMdPreview, setShowMdPreview] = React.useState<boolean>(() => !!initialDraftRef.current?.showMdPreview);
|
||||
const [originalAuthor, setOriginalAuthor] = React.useState<string>(() => {
|
||||
|
|
@ -287,7 +288,7 @@ export default function HackSubmitForm({
|
|||
const data = JSON.parse(raw);
|
||||
if (data && typeof data === "object") {
|
||||
const isEmpty =
|
||||
!title && !summary && !description && !baseRom && !platform && !version && !language && !completionStatus && !boxArt && !discord && !twitter && !pokecommunity && !github && (!tags || tags.length === 0) && !originalAuthor;
|
||||
!title && !summary && !description && !baseRom && !platform && !version && !language && !completionStatus && !boxArt && !discord && !twitter && !pokecommunity && !github && !verificationContactInfo && (!tags || tags.length === 0) && !originalAuthor;
|
||||
if (isEmpty) {
|
||||
let applied = false;
|
||||
if (typeof data.title === "string") setTitle(data.title);
|
||||
|
|
@ -316,6 +317,8 @@ export default function HackSubmitForm({
|
|||
if (typeof data.pokecommunity === "string") applied = applied || !!data.pokecommunity;
|
||||
if (typeof data.github === "string") setGithub(data.github);
|
||||
if (typeof data.github === "string") applied = applied || !!data.github;
|
||||
if (typeof data.verificationContactInfo === "string") setVerificationContactInfo(data.verificationContactInfo);
|
||||
if (typeof data.verificationContactInfo === "string") applied = applied || !!data.verificationContactInfo;
|
||||
if (Array.isArray(data.tags)) setTags(data.tags.filter((t: any) => typeof t === "string"));
|
||||
if (Array.isArray(data.tags)) applied = applied || data.tags.length > 0;
|
||||
// Only load originalAuthor from draft if customCreator is not provided
|
||||
|
|
@ -346,7 +349,7 @@ export default function HackSubmitForm({
|
|||
if (!d || typeof d !== "object") return;
|
||||
// Don't count originalAuthor if customCreator is provided
|
||||
const hasAny = Boolean(
|
||||
d.title || d.summary || d.description || d.baseRom || d.platform || d.version || d.language || d.completionStatus || d.boxArt || d.discord || d.twitter || d.pokecommunity || d.github || (Array.isArray(d.tags) && d.tags.length > 0) || (!customCreator && d.originalAuthor)
|
||||
d.title || d.summary || d.description || d.baseRom || d.platform || d.version || d.language || d.completionStatus || d.boxArt || d.discord || d.twitter || d.pokecommunity || d.github || d.verificationContactInfo || (Array.isArray(d.tags) && d.tags.length > 0) || (!customCreator && d.originalAuthor)
|
||||
);
|
||||
if (hasAny) { hydratedFromDraftRef.current = true; setRestoredDraft(true); }
|
||||
}, [dummy, draftKey, customCreator]);
|
||||
|
|
@ -369,6 +372,7 @@ export default function HackSubmitForm({
|
|||
twitter,
|
||||
pokecommunity,
|
||||
github,
|
||||
verificationContactInfo,
|
||||
tags,
|
||||
step,
|
||||
showMdPreview,
|
||||
|
|
@ -402,6 +406,7 @@ export default function HackSubmitForm({
|
|||
twitter,
|
||||
pokecommunity,
|
||||
github,
|
||||
verificationContactInfo,
|
||||
tags,
|
||||
originalAuthor,
|
||||
customCreator,
|
||||
|
|
@ -441,6 +446,7 @@ export default function HackSubmitForm({
|
|||
if (twitter) fd.set('twitter', twitter);
|
||||
if (pokecommunity) fd.set('pokecommunity', pokecommunity);
|
||||
if (github) fd.set('github', github);
|
||||
if (verificationContactInfo) fd.set('verification_contact_info', verificationContactInfo);
|
||||
if (tags.length) fd.set('tags', tags.join(','));
|
||||
if (isArchive) {
|
||||
fd.set('is_archive', 'true');
|
||||
|
|
@ -724,6 +730,7 @@ export default function HackSubmitForm({
|
|||
setTwitter("");
|
||||
setPokecommunity("");
|
||||
setGithub("");
|
||||
setVerificationContactInfo("");
|
||||
setTags([]);
|
||||
setNewCoverFiles([]);
|
||||
setCoverErrors([]);
|
||||
|
|
@ -1146,6 +1153,36 @@ export default function HackSubmitForm({
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!profile?.verified && (
|
||||
<div className="grid gap-2">
|
||||
<label className="text-sm text-foreground/80">Verification Contact Information <span className="text-foreground/60">(Recommended)</span></label>
|
||||
<p className="text-xs text-foreground/60">
|
||||
Help us verify your account by providing contact information from a platform where your message/post history can be verified (e.g., Discord, PokéCommunity). This information will only be visible to admins during the approval process.
|
||||
</p>
|
||||
{!isDummy ? (
|
||||
<textarea
|
||||
value={verificationContactInfo}
|
||||
onChange={(e) => setVerificationContactInfo(e.target.value)}
|
||||
placeholder={`Discord username: @example
|
||||
I am active in the following servers:
|
||||
Team Aqua's Hideout, RH Hideout, pret
|
||||
|
||||
Here is an invite to my development server:
|
||||
https://discord.gg/example`}
|
||||
rows={6}
|
||||
className="rounded-md bg-[var(--surface-2)] px-3 py-2 text-sm ring-1 ring-inset ring-[var(--border)] focus:outline-none focus:ring-2 focus:ring-[var(--ring)] resize-y"
|
||||
/>
|
||||
) : (
|
||||
<div className="rounded-md bg-[var(--surface-2)] px-3 py-2 text-sm ring-1 ring-inset ring-[var(--border)] text-foreground/60 select-none min-h-[6rem]">
|
||||
Discord: @example<br />
|
||||
I am active in the following servers: Team Aqua's Hideout, pret, and PokéDev School<br />
|
||||
Here is an invite to my development server: https://discord.gg/example_server_invite
|
||||
</div>
|
||||
)}
|
||||
<p className="text-xs text-foreground/60">Optional but recommended for faster account verification. Please be detailed.</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ export type Database = {
|
|||
summary: string
|
||||
title: string
|
||||
updated_at: string | null
|
||||
verification_contact_info: string | null
|
||||
version: string
|
||||
}
|
||||
Insert: {
|
||||
|
|
@ -195,6 +196,7 @@ export type Database = {
|
|||
summary: string
|
||||
title: string
|
||||
updated_at?: string | null
|
||||
verification_contact_info?: string | null
|
||||
version: string
|
||||
}
|
||||
Update: {
|
||||
|
|
@ -229,6 +231,7 @@ export type Database = {
|
|||
summary?: string
|
||||
title?: string
|
||||
updated_at?: string | null
|
||||
verification_contact_info?: string | null
|
||||
version?: string
|
||||
}
|
||||
Relationships: [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
alter table if exists public.hacks
|
||||
add column if not exists verification_contact_info text;
|
||||
Loading…
Reference in New Issue
Block a user