diff --git a/app/student/super-listing/paraluman/layout.tsx b/app/student/super-listing/paraluman/layout.tsx new file mode 100644 index 00000000..ff7508ee --- /dev/null +++ b/app/student/super-listing/paraluman/layout.tsx @@ -0,0 +1,32 @@ +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: + "BetterInternship x Paraluman News: Multilingual News Delivery Challenge", + description: + "Design a practical multilingual publishing solution for Paraluman News that balances speed, accuracy, editorial integrity, and reader trust.", + openGraph: { + title: + "BetterInternship x Paraluman News: Multilingual News Delivery Challenge", + description: + "Design a practical multilingual publishing solution for Paraluman News that balances speed, accuracy, editorial integrity, and reader trust.", + url: "/student/super-listing/paraluman", + siteName: "BetterInternship", + type: "website", + }, + twitter: { + card: "summary_large_image", + title: + "BetterInternship x Paraluman News: Multilingual News Delivery Challenge", + description: + "Design a practical multilingual publishing solution for Paraluman News that balances speed, accuracy, editorial integrity, and reader trust.", + }, +}; + +export default function ParalumanLayout({ + children, +}: { + children: React.ReactNode; +}) { + return <>{children}; +} diff --git a/app/student/super-listing/paraluman/page.tsx b/app/student/super-listing/paraluman/page.tsx new file mode 100644 index 00000000..5067cf0e --- /dev/null +++ b/app/student/super-listing/paraluman/page.tsx @@ -0,0 +1,513 @@ +"use client"; + +import { + type ChangeEvent, + type FormEvent, + useMemo, + useRef, + useState, +} from "react"; +import Link from "next/link"; +import Image from "next/image"; +import { ArrowUpRight, Loader2 } from "lucide-react"; +import { JetBrains_Mono, Space_Grotesk } from "next/font/google"; +import { Button } from "@/components/ui/button"; +import { Dialog, DialogContent } from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { SuperListingBadge } from "@/components/shared/jobs"; +import { cn } from "@/lib/utils"; +import { Loader } from "@/components/ui/loader"; +import { Turnstile } from "@marsidev/react-turnstile"; +import { Badge } from "@/components/ui/badge"; + +const headingFont = Space_Grotesk({ + subsets: ["latin"], + weight: ["500", "700"], + variable: "--font-paraluman-heading", +}); + +const monoFont = JetBrains_Mono({ + subsets: ["latin"], + weight: ["400", "600"], + variable: "--font-paraluman-mono", +}); + +const CHALLENGE_WORKFLOW = [ + { + title: "Input", + body: "Submit English article", + }, + { + title: "Generate", + body: "Create Filipino version", + }, + { + title: "Review", + body: "Approve before publish", + }, + { + title: "Publish", + body: "Release both versions", + }, +]; + +const REQUIRED_FEATURES = [ + "Login system", + "Submit & view articles", + "See Filipino translation", + "Approve/reject versions", + "View published results", +]; + +const DELIVERABLES = [ + "1-page design note", + "Working prototype", + "Demo login credentials", +]; + +const EVALUATION_CRITERIA = ["Clarity", "Practicality", "Flow", "Tradeoffs"]; + +type ParalumanSubmissionPayload = { + fullName: string; + email: string; + portfolioUrl: string; + linkedinUrl: string; + whyFit: string; +}; + +type ParalumanSubmissionResponse = { + success: boolean; + message?: string; +}; + +const INITIAL_FORM_STATE: ParalumanSubmissionPayload = { + fullName: "", + email: "", + portfolioUrl: "", + linkedinUrl: "", + whyFit: "", +}; + +export default function ParalumanPage() { + const [form, setForm] = + useState(INITIAL_FORM_STATE); + const [isSubmitting, setIsSubmitting] = useState(false); + const [resultMessage, setResultMessage] = useState(""); + const [isError, setIsError] = useState(false); + const [submitModalOpen, setSubmitModalOpen] = useState(false); + const [token, setToken] = useState(""); + const [tokenFail, setTokenFail] = useState(false); + + const challengeRef = useRef(null); + + const endpoint = useMemo(() => { + const base = process.env.NEXT_PUBLIC_API_URL?.replace(/\/$/, ""); + if (!base) return "/api/super-listings/paraluman-submission"; + return `${base}/super-listings/paraluman-submission`; + }, []); + + const updateField = + (field: keyof ParalumanSubmissionPayload) => + ( + event: ChangeEvent | ChangeEvent, + ) => { + setForm((previous) => ({ ...previous, [field]: event.target.value })); + }; + + const handleSubmit = async (event: FormEvent) => { + event.preventDefault(); + setResultMessage(""); + setIsError(false); + setIsSubmitting(true); + + try { + const response = await fetch(endpoint, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ ...form, "cf-token": token }), + }); + + const data = (await response.json()) as ParalumanSubmissionResponse; + + if (!response.ok || !data.success) { + throw new Error(data.message || "Could not send your submission."); + } + + setForm(INITIAL_FORM_STATE); + setResultMessage( + "Submission sent to your email with the BetterInternship team in CC.", + ); + } catch (error) { + setIsError(true); + setResultMessage( + error instanceof Error + ? error.message + : "Something went wrong while sending your submission.", + ); + } finally { + setIsSubmitting(false); + } + }; + + const openSubmitModal = () => { + setResultMessage(""); + setIsError(false); + setSubmitModalOpen(true); + }; + + const scrollToChallenge = () => { + challengeRef.current?.scrollIntoView({ + behavior: "smooth", + block: "start", + }); + }; + + return ( +
+
+
+
+ +
+
+ + BetterInternship + + + × + + + Paraluman News + +
+
+ +
+
+
+ + +

+ Build the + + Future of + + Journalism +

+ +
+ + Multilingual Publishing Challenge + +
+ +
+

+ Make{" "} + + journalism accessible across languages + + . Build a real system that publishes articles in English and + Filipino simultaneously, with human review at every step. +

+

+ Build something real. Ship it. +

+
+
+ +
+
+
+ +
+
+
+
+ +
+
+ +
+ +
+
+
+
+

+ What You Build +

+

+ A system that publishes a news article in English and Filipino + at the same time. +

+
+ +
+
+ {CHALLENGE_WORKFLOW.map((item) => ( +
+
+
+

+ {item.title} +

+

+ {item.body} +

+
+
+ ))} +
+ +
+
+
+
+

+ Deliverables +

+
    + {DELIVERABLES.map((item) => ( +
  • - {item}
  • + ))} +
+
+
+ +
+
+
+

+ Prototype Must Allow +

+
    + {REQUIRED_FEATURES.map((item) => ( +
  • - {item}
  • + ))} +
+
+
+ +
+
+
+

+ Evaluation Criteria +

+

+ {EVALUATION_CRITERIA.join(" • ")} +

+
+
+ +
+
+
+

+ Constraint +

+

+ Small team. Limited budget. Keep it simple. +

+
+
+
+ +
+

+ + The Challenge: + {" "} + How do you make reliable journalism accessible across + languages—without slowing it down? +

+
+ +
+
+
+ +
+
+
+
+
+
+ + { + setSubmitModalOpen(open); + if (!open) { + setResultMessage(""); + setIsError(false); + } + }} + > + +
+
+
+ +
+

+ Candidate Submission +

+

+ Ship Your Proposal +

+
+ + {token ? ( +
+
void handleSubmit(e)} + > +
+ + +
+ +
+ + +
+ +