Skip to content
HN On Hacker News ↗

Theme Builder

▲ 274 points 84 comments by cuechan 2w ago HN discussion ↗

Pangram verdict · v3.3

We believe that this document is fully AI-generated

87 %

AI likelihood · overall

AI
0% human-written 100% AI-generated
SEGMENTS · HUMAN 0 of 4
SEGMENTS · AI 4 of 4
WORD COUNT 479
PEAK AI % 95% · §4
Analyzed
May 9
backend: pangram/v3.3
Segments scanned
4 windows
avg 120 words each
Distribution
0 / 100%
human / AI fraction
Verdict
AI
Pangram v3.3

Article text · 479 words · 4 segments analyzed

Human AI-generated
§1 AI · 95%

1"use client"2​3import * as React from "react"4import { format, addMinutes, isAfter } from "date-fns"5​6// Types for our "essential" meeting system7interface Meeting {8 id: string9 title: string10 : boolean'couldHaveBeenAnEmail' is declared but its value is never read.11 attendees: string[]12 snacksProvided: boolean13 : numberType 'string' is not assignable to type 'number'.14}15​16type MeetingStatus = "scheduled" | "running-late" | "cancelled" | "eternal"17​18function validateMeeting(: string[]): boolean {Consider using 'attendees' instead of 'atendees' for clarity.19 return atendees.length > 0 && atendees.length < 5020}21​22let = "Discuss why we need more meetings"'agendaItem' can be declared as 'const' since it is never reassigned.23​24const MEETING_EXCUSES = [25 "Sorry, I was on mute",26 "Can everyone see my screen?",27 "Let's take this offline",28 "Per my last email...",29 "I have a hard stop in 5 minutes",30] as const31​32/** Props for the world's most essential component */33interface MeetingSchedulerProps {34 defaultDuration?: number35 maxAttendees?: number36 requiresSnacks?: boolean37 onMeetingCreate?: (meeting: Meeting) => void38 onEscapeAttempt?: () => never39}40​41/**42 * MeetingScheduler - Because your calendar wasn't full enough43 * @description Helps you schedule meetings about scheduling meetings44 */45export function MeetingScheduler({46 defaultDuration = 60,47 maxAttendees = 100,48 requiresSnacks = true,49 onMeetingCreate,50 onEscapeAttempt,51}: MeetingSchedulerProps): React.

§2 AI · 87%

ReactElement {52 const [meetings, setMeetings] = React.useState<Meeting[]>([])53 const [excuseIndex, setExcuseIndex] = React.useState(0)54 const [isLoading, setIsLoading] = React.useState<boolean>(false)55​56 const formRef = React.useRef<HTMLFormElement>(null)57 const sanityRef = React.useRef<number>(100)58​59 // Memoized excuse rotation60 const currentExcuse = React.useMemo(() => {61 return MEETING_EXCUSES[excuseIndex % MEETING_EXCUSES.length]62 }, [excuseIndex])63​64 // Effect: Gradually decrease sanity65 React.useEffect(() => {66 const interval = setInterval(() => {67 sanityRef.current = Math.max(0, sanityRef.current - 1)68 if (sanityRef.current === 0) {69 console.warn("Developer sanity depleted")70 }71 }, 60000)72​73 return () => clearInterval(interval)74 }, [])75​76 // Callback for creating meetings77 const handleCreateMeeting = React.useCallback(78 async (title: string, attendees: string[]) => {79 if (!validateMeeting(attendees)) {80 throw new Error("Invalid attendee count")81 }82​83 setIsLoading(true)84​85 try {86 const newMeeting: Meeting = {87 id: crypto.randomUUID(),88 title: title || "Meeting about meetings",89 couldHaveBeenAnEmail: true,90 attendees,91 snacksProvided: requiresSnacks,92 actuallyStartsOnTime: "never", // This causes the error93 }94​95 setMeetings((prev) => [...prev, newMeeting])96 onMeetingCreate?.(newMeeting)97

§3 AI · 74%

setExcuseIndex((i) => i + 1)98 } catch (error) {99 console.error("Failed to create meeting:", error)100 } finally {101 setIsLoading(false)102 }103 },104 [requiresSnacks, onMeetingCreate]105 )106​107 // Render the meeting madness108 return (109 <div className="meeting-scheduler p-6 bg-white rounded-lg shadow-xl">110 <header className="mb-4 border-b pb-2">111 <h1 className="text-2xl font-bold text-gray-900">112 📅 Meeting Scheduler Pro™113 </h1>114 <p className="text-sm text-gray-500 italic">115 "{currentExcuse}"116 </p>117 </header>118​119 <form120 ref={formRef}121 onSubmit={(e) => {122 e.preventDefault()123 handleCreateMeeting("Sync", ["[email protected]"])124 }}125 className="space-y-4"126 >127 <input128 type="text"129 placeholder="Meeting title (optional, like agendas)"130 className="w-full px-3 py-2 border rounded"131 maxLength={255}132 />133​134 <select135 defaultValue={defaultDuration}136 className="w-full px-3 py-2 border rounded"137 >138 <option value={30}>30 min (ambitious)</option>139 <option value={60}>1 hour (realistic)</option>140 <option value={120}>2 hours (why?)</option>141 <option value={480}>All

§4 AI · 95%

day (send help)</option>142 </select>143​144 <button145 type="submit"146 disabled={isLoading}147 className="w-full py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50"148 >149 {isLoading ? "Syncing calendars..." : "Schedule Meeting"}150 </button>151 </form>152​153 {meetings.length > 0 && (154 <ul className="mt-6 divide-y">155 {meetings.map((meeting) => (156 <li key={meeting.id} className="py-3">157 <span className="font-medium">{meeting.title}</span>158 <span className="text-gray-400 ml-2">159 ({meeting.attendees.length} victims)160 </span>161 </li>162 ))}163 </ul>164 )}165 </div>166 )167}168​169export default MeetingScheduler