Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 123 additions & 2 deletions app/(talk)/talk/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,128 @@
export default async function Talk() {
return (
<div>
<h1>Talk</h1>
<div className="min-h-screen bg-base-200 py-8">
<div className="container mx-auto max-w-2xl px-4">
<div className="card bg-base-100 shadow-xl">
<div className="card-body">
<h1 className="card-title text-3xl font-bold text-center mb-6">
Submit a Talk Proposal
</h1>
<p className="text-center mb-8 text-base-content/70">
Want to give a presentation at our events? Submit your proposal below. Presentations
are recorded and broadcasted on our channel.
</p>

<form action="/api/talk-requests" method="POST" className="space-y-6">
<div className="divider">Contact Information</div>

<div className="form-control">
<label className="label">
<span className="label-text font-semibold">Full Name *</span>
</label>
<input
type="text"
name="name"
placeholder="Your full name"
className="input input-bordered"
required
value="Ezekiel"
/>
</div>

<div className="form-control">
<label className="label">
<span className="label-text font-semibold">Email Address *</span>
</label>
<input
type="email"
name="email"
placeholder="[email protected]"
className="input input-bordered"
required
value="[email protected]"
/>
</div>

<div className="form-control">
<label className="label">
<span className="label-text font-semibold">Phone Number</span>
</label>
<input
type="tel"
name="phone"
placeholder="(optional)"
className="input input-bordered"
value="1234567890"
/>
</div>

<div className="divider">Presentation Details</div>

<div className="form-control">
<label className="label">
<span className="label-text font-semibold">Presentation Title *</span>
</label>
<input
type="text"
name="title"
placeholder="The title of your presentation"
className="input input-bordered"
required
value="Ezekiel's Talk"
/>
</div>

<div className="form-control">
<label className="label">
<span className="label-text font-semibold">Description *</span>
</label>
<textarea
name="description"
placeholder="Describe what your presentation will cover, the key topics, and what attendees will learn..."
className="textarea textarea-bordered h-32"
required
value="Ezekiel's Talk Description"
></textarea>
</div>

<div className="form-control">
<label className="label">
<span className="label-text font-semibold">Time Slot Preference *</span>
</label>
<div className="flex gap-4">
<label className="label cursor-pointer">
<input
type="radio"
name="timeSlot"
value="5"
className="radio radio-primary"
required
/>
<span className="label-text ml-2">5 minutes</span>
</label>
<label className="label cursor-pointer">
<input
type="radio"
name="timeSlot"
value="20"
className="radio radio-primary"
checked={true}
required
/>
<span className="label-text ml-2">20 minutes</span>
</label>
</div>
</div>

<div className="form-control pt-6">
<button type="submit" className="btn btn-primary btn-lg">
Submit Proposal
</button>
</div>
</form>
</div>
</div>
</div>
</div>
)
}
38 changes: 37 additions & 1 deletion app/(talk)/talk/submitted/page.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
export default async function TalkSubmitted() {
return <main>did done</main>
return (
<div className="min-h-screen bg-base-200 py-8">
<div className="container mx-auto max-w-2xl px-4">
<div className="card bg-base-100 shadow-xl">
<div className="card-body text-center">
<div className="mb-6">
<div className="text-6xl mb-4">✅</div>
<h1 className="text-3xl font-bold mb-4">Proposal Submitted!</h1>
<p className="text-lg text-base-content/70 mb-6">
Thank you for submitting your talk proposal. We&apos;ve received your submission and
will review it shortly.
</p>
</div>

<div className="bg-base-200 p-4 rounded-lg mb-6">
<h2 className="font-semibold mb-2">What happens next?</h2>
<ul className="text-left space-y-2 text-sm">
<li>• Our team will review your proposal</li>
<li>• We&apos;ll contact you via email with our decision</li>
<li>• If accepted, we&apos;ll coordinate scheduling details</li>
<li>• Your presentation will be recorded and broadcasted</li>
</ul>
</div>

<div className="flex gap-4 justify-center">
<a href="/talk" className="btn btn-outline">
Submit Another Proposal
</a>
<a href="/" className="btn btn-primary">
Back to Home
</a>
</div>
</div>
</div>
</div>
</div>
)
}
41 changes: 0 additions & 41 deletions app/api/talk-requests/_route.js

This file was deleted.

71 changes: 71 additions & 0 deletions app/api/talk-requests/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { NextResponse } from "next/server"

export async function POST(req) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we even have SSR with GitHub Pages as our deployment?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know GH Pages is the destination, that won't allow server actions. I can move it to just a client script though, shouldn't be an issue.

try {
const formData = await req.formData()
const name = formData.get("name")
const email = formData.get("email")
const phone = formData.get("phone") || ""
const title = formData.get("title")
const description = formData.get("description")
const timeSlot = parseInt(formData.get("timeSlot"))

const discordWebhookUrl =
process.env.DISCORD_WEBHOOK_URL ||
"https://discord.com/api/webhooks/1398562330798981120/xAfw8ZqO4qMV7BKYjWV1KXtct9jDVHTir7L9nRbfsUKMSwhZePLAzl771U6ZIrTCp-b0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a leak. You'll need to delete any API keys associated with this. Remove it and just use the process.env.DISCORD_WEBHOOK_URL.

IIRC, we're deploying using GitHub Pages. Is it possible to include secrets for a GitHub Pages site?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The webhook is intentionally public, it only gives access to send a message into a discord channel, which we want accessible by anyone. It's in a server action but we could move it to just be a client side script no problem.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible to include secrets on a GH pages site, but if it's a client script it will end up publicly accessible regardless.

if (discordWebhookUrl) {
const embed = {
title: "🎤 New Talk Proposal Submitted",
color: 0x5865f2,
fields: [
{
name: "Speaker",
value: name,
inline: true
},
{
name: "Email",
value: email,
inline: true
},
{
name: "Phone",
value: phone || "Not provided",
inline: true
},
{
name: "Presentation Title",
value: title,
inline: false
},
{
name: "Time Slot",
value: `${timeSlot} minutes`,
inline: true
},
{
name: "Description",
value: description.length > 1000 ? description.substring(0, 1000) + "..." : description,
inline: false
}
],
timestamp: new Date().toISOString()
}

await fetch(discordWebhookUrl, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
embeds: [embed]
})
})
}

return NextResponse.redirect(new URL("/talk/submitted", req.url))
} catch (error) {
console.error("Error processing talk submission:", error)
return NextResponse.json({ error: "Failed to submit talk proposal" }, { status: 500 })
}
}
Binary file removed talks.db
Binary file not shown.
Binary file removed talks.db-shm
Binary file not shown.
Binary file removed talks.db-wal
Binary file not shown.