-
Notifications
You must be signed in to change notification settings - Fork 6
Talk application page #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
132941e
d00bf06
792c7a3
e19a4a3
22e0ba4
f611dcd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import { ReactNode } from "react" | ||
| import type { Metadata } from "next" | ||
| import "../globals.css" | ||
| import { Header } from "../components/Header" | ||
| import { siteConfig } from "../siteConfig" | ||
| import StyledComponentsRegistry from "../StyledComponentsRegistry" | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: siteConfig.title, | ||
| description: siteConfig.description, | ||
| openGraph: { | ||
| type: "website", | ||
| url: siteConfig.url, | ||
| title: siteConfig.title, | ||
| description: siteConfig.description, | ||
| images: siteConfig.ogImage | ||
| } | ||
| } | ||
|
|
||
| export default function TalkRootLayout({ | ||
| children | ||
| }: Readonly<{ | ||
| children: ReactNode | ||
| }>) { | ||
| return ( | ||
| <html lang="en"> | ||
| <head> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
| <link rel="icon" href="/images/favicon.png" /> | ||
| </head> | ||
| <body> | ||
| <StyledComponentsRegistry> | ||
| <Header opacity={0} /> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just use
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. overrides on browser font settings will result in variable height for the header content. We could use js to determine height on load/resize and update margin-top. We could use a "magic-number" for margin-top that is "good enough" in most situations. We could use position sticky, which is probably what we actually want, but it can have some unintended design consequences if we use any different stacking context. I think that the inclusion of an invisible element is the most consistent and effective way to handle the spacing at top, and is clear in the jsx what the intended purpose is. |
||
| <Header /> | ||
| {children} | ||
| </StyledComponentsRegistry> | ||
| </body> | ||
| </html> | ||
| ) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| body { | ||
| font-size: 18pt; | ||
| } | ||
|
|
||
| form { | ||
| display: grid; | ||
| grid-template-columns: 1fr 1fr; | ||
| gap: 0.5em; | ||
| padding: 0.5em; | ||
| } | ||
|
|
||
| input, | ||
| textarea, | ||
| button { | ||
| font-size: inherit; | ||
| padding: 0.5em; | ||
| } | ||
|
|
||
| textarea { | ||
| grid-column: span 2; | ||
| resize: vertical; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,243 @@ | ||
| export default async function Talk() { | ||
| return ( | ||
| <div className="min-h-screen bg-gradient-to-br from-primary/10 via-base-200 to-secondary/10 py-4 sm:py-8"> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This commit should be squashed with the "Add talk submission form" commit |
||
| <div className="container mx-auto max-w-2xl px-3 sm:px-4"> | ||
| <div className="card bg-base-100/95 backdrop-blur-sm shadow-2xl border border-base-300/50"> | ||
| <div className="card-body p-4 sm:p-8"> | ||
| <div className="text-center mb-8"> | ||
| <div className="mb-4"> | ||
| <div className="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-r from-primary to-secondary rounded-full mb-4"> | ||
| <span className="text-2xl">🎤</span> | ||
| </div> | ||
| </div> | ||
| <h1 className="text-2xl sm:text-4xl font-bold bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent mb-4"> | ||
| Submit a Talk Proposal | ||
| </h1> | ||
| <p className="text-sm sm:text-base text-base-content/70 max-w-lg mx-auto leading-relaxed"> | ||
| Share your expertise with our community! Your presentation will be recorded and | ||
| broadcasted to reach developers worldwide. | ||
| </p> | ||
| </div> | ||
|
|
||
| <div className="w-full bg-base-300 rounded-full h-2 mb-8"> | ||
| <div | ||
| className="bg-gradient-to-r from-primary to-secondary h-2 rounded-full w-0" | ||
| id="progress-bar" | ||
| ></div> | ||
| </div> | ||
|
|
||
| <form action="/api/talk-requests" method="POST" className="space-y-6" id="talk-form"> | ||
| <div className="divider divider-start"> | ||
| <span className="bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent font-semibold"> | ||
| 👤 Contact Information | ||
| </span> | ||
| </div> | ||
|
|
||
| <div className="grid grid-cols-1 sm:grid-cols-2 gap-4"> | ||
| <div className="form-control sm:col-span-2"> | ||
| <label className="label"> | ||
| <span className="label-text font-semibold flex items-center gap-2"> | ||
| <span className="text-primary">👨💼</span> | ||
| Full Name * | ||
| </span> | ||
| </label> | ||
| <input | ||
| type="text" | ||
| name="name" | ||
| placeholder="Your full name" | ||
| className="input input-bordered focus:input-primary transition-all duration-300 hover:shadow-md" | ||
| required | ||
| defaultValue="" | ||
| /> | ||
| </div> | ||
|
|
||
| <div className="form-control"> | ||
| <label className="label"> | ||
| <span className="label-text font-semibold flex items-center gap-2"> | ||
| <span className="text-primary">📧</span> | ||
| Email * | ||
| </span> | ||
| </label> | ||
| <input | ||
| type="email" | ||
| name="email" | ||
| placeholder="[email protected]" | ||
| className="input input-bordered focus:input-primary transition-all duration-300 hover:shadow-md" | ||
| required | ||
| defaultValue="" | ||
| /> | ||
| </div> | ||
|
|
||
| <div className="form-control"> | ||
| <label className="label"> | ||
| <span className="label-text font-semibold flex items-center gap-2"> | ||
| <span className="text-primary">📱</span> | ||
| Phone | ||
| </span> | ||
| </label> | ||
| <input | ||
| type="tel" | ||
| name="phone" | ||
| placeholder="(555) 123-4567" | ||
| className="input input-bordered focus:input-primary transition-all duration-300 hover:shadow-md" | ||
| defaultValue="" | ||
| /> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className="divider divider-start"> | ||
| <span className="bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent font-semibold"> | ||
| 🎯 Presentation Details | ||
| </span> | ||
| </div> | ||
|
|
||
| <div className="form-control"> | ||
| <label className="label"> | ||
| <span className="label-text font-semibold flex items-center gap-2"> | ||
| <span className="text-primary">🏷️</span> | ||
| Presentation Title * | ||
| </span> | ||
| </label> | ||
| <input | ||
| type="text" | ||
| name="title" | ||
| placeholder="e.g., Building Scalable React Applications" | ||
| className="input input-bordered focus:input-primary transition-all duration-300 hover:shadow-md" | ||
| required | ||
| defaultValue="" | ||
| /> | ||
| </div> | ||
|
|
||
| <div className="form-control"> | ||
| <label className="label"> | ||
| <span className="label-text font-semibold flex items-center gap-2"> | ||
| <span className="text-primary">📝</span> | ||
| Description * | ||
| </span> | ||
| </label> | ||
| <textarea | ||
| name="description" | ||
| placeholder="Describe your presentation topic, key takeaways, and what attendees will learn. Be specific about technologies, concepts, or methodologies you'll cover..." | ||
| className="textarea textarea-bordered h-32 focus:textarea-primary transition-all duration-300 hover:shadow-md resize-none" | ||
| required | ||
| defaultValue="" | ||
| ></textarea> | ||
| <label className="label"> | ||
| <span className="label-text-alt text-base-content/60"> | ||
| Tip: Include your experience level and target audience | ||
| </span> | ||
| </label> | ||
| </div> | ||
|
|
||
| <div className="form-control"> | ||
| <label className="label"> | ||
| <span className="label-text font-semibold flex items-center gap-2 mb-3"> | ||
| <span className="text-primary">⏰</span> | ||
| Time Slot Preference * | ||
| </span> | ||
| </label> | ||
| <div className="grid grid-cols-1 sm:grid-cols-2 gap-3"> | ||
| <label className="cursor-pointer"> | ||
| <input | ||
| type="radio" | ||
| name="timeSlot" | ||
| value="5" | ||
| className="sr-only peer" | ||
| required | ||
| /> | ||
| <div className="card bg-base-200 hover:bg-primary/10 peer-checked:bg-primary peer-checked:text-primary-content transition-all duration-300 hover:shadow-md peer-checked:shadow-lg border-2 border-transparent peer-checked:border-primary"> | ||
| <div className="card-body p-4 text-center"> | ||
| <div className="text-2xl mb-2">⚡</div> | ||
| <h3 className="font-bold">Lightning Talk</h3> | ||
| <p className="text-sm opacity-70">5 minutes</p> | ||
| <p className="text-xs mt-1">Quick insights & demos</p> | ||
| </div> | ||
| </div> | ||
| </label> | ||
| <label className="cursor-pointer"> | ||
| <input | ||
| type="radio" | ||
| name="timeSlot" | ||
| value="20" | ||
| className="sr-only peer" | ||
| required | ||
| /> | ||
| <div className="card bg-base-200 hover:bg-primary/10 peer-checked:bg-primary peer-checked:text-primary-content transition-all duration-300 hover:shadow-md peer-checked:shadow-lg border-2 border-transparent peer-checked:border-primary"> | ||
| <div className="card-body p-4 text-center"> | ||
| <div className="text-2xl mb-2">🎯</div> | ||
| <h3 className="font-bold">Standard Talk</h3> | ||
| <p className="text-sm opacity-70">20 minutes</p> | ||
| <p className="text-xs mt-1">Deep dive & examples</p> | ||
| </div> | ||
| </div> | ||
| </label> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className="form-control pt-6"> | ||
| <button | ||
| type="submit" | ||
| className="btn btn-primary btn-lg w-full text-lg font-bold bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 transition-all duration-300 hover:shadow-lg hover:scale-[1.02] active:scale-[0.98]" | ||
| > | ||
| <span className="mr-2">🚀</span> | ||
| Submit Your Proposal | ||
| <span className="ml-2">✨</span> | ||
| </button> | ||
| </div> | ||
| </form> | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
| <script | ||
| dangerouslySetInnerHTML={{ | ||
| __html: ` | ||
| document.addEventListener('DOMContentLoaded', function() { | ||
| const form = document.getElementById('talk-form'); | ||
| const progressBar = document.getElementById('progress-bar'); | ||
| const inputs = form.querySelectorAll('input[required], textarea[required]'); | ||
|
|
||
| function updateProgress() { | ||
| const filledInputs = Array.from(inputs).filter(input => { | ||
| if (input.type === 'radio') { | ||
| return form.querySelector('input[name="' + input.name + '"]:checked'); | ||
| } | ||
| return input.value.trim() !== ''; | ||
| }); | ||
|
|
||
| // Remove duplicates for radio buttons | ||
| const uniqueNames = new Set(); | ||
| const uniqueFilledInputs = filledInputs.filter(input => { | ||
| if (input.type === 'radio') { | ||
| if (uniqueNames.has(input.name)) return false; | ||
| uniqueNames.add(input.name); | ||
| return true; | ||
| } | ||
| return true; | ||
| }); | ||
|
|
||
| const progress = (uniqueFilledInputs.length / 5) * 100; // 5 required fields total | ||
| progressBar.style.width = progress + '%'; | ||
| } | ||
|
|
||
| inputs.forEach(input => { | ||
| input.addEventListener('input', updateProgress); | ||
| input.addEventListener('change', updateProgress); | ||
| }); | ||
|
|
||
| // Add loading state on form submit | ||
| form.addEventListener('submit', function(e) { | ||
| const submitBtn = form.querySelector('button[type="submit"]'); | ||
| submitBtn.innerHTML = '<span class="loading loading-spinner loading-sm mr-2"></span>Submitting...'; | ||
| submitBtn.disabled = true; | ||
| }); | ||
|
|
||
| // Initial progress calculation | ||
| updateProgress(); | ||
| }); | ||
| ` | ||
| }} | ||
| /> | ||
| </div> | ||
| ) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This commit "Remove layout, page, and styles for Talk and Events sections" would be removed if we only had one layout file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, I can restructure to have one layout that's more dynamic instead of using two layouts.