Add advertisement page

pull/6827/head
Kamran Ahmed 3 months ago
parent 877c79b120
commit a8aba9e6de
  1. 227
      src/components/AdvertiseForm.tsx
  2. 15
      src/components/Footer.astro
  3. 6
      src/components/NavigationDropdown.tsx
  4. 39
      src/pages/advertise.astro

@ -0,0 +1,227 @@
import React, { useState } from 'react';
import { CheckIcon } from './ReactIcons/CheckIcon.tsx';
import { pageProgressMessage } from '../stores/page.ts';
import { httpPost } from '../lib/http.ts';
type InputProps = {
label: string;
name: string;
type: string;
value: string;
onChange: (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => void;
required?: boolean;
rows?: number;
};
function Input(props: InputProps) {
const { label, name, type, value, onChange, required, rows } = props;
return (
<div className="mb-4">
<label htmlFor={name} className="block text-sm font-medium text-gray-700">
{label} {required && <span className="text-red-500">*</span>}
</label>
{type === 'textarea' ? (
<textarea
placeholder={label}
id={name}
name={name}
value={value}
onChange={onChange}
rows={rows}
className="mt-1 block w-full rounded-md border border-gray-300 p-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
autoComplete="off"
data-1p-ignore=""
data-form-type="other"
data-lpignore="true"
></textarea>
) : (
<input
type={type}
id={name}
placeholder={label}
name={name}
value={value}
onChange={onChange}
required={required}
className="mt-1 block w-full rounded-md border border-gray-300 p-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
autoComplete="off"
data-1p-ignore=""
data-form-type="other"
data-lpignore="true"
/>
)}
</div>
);
}
export function AdvertiseForm() {
const [status, setStatus] = useState<'submitting' | 'submitted'>();
const [error, setError] = useState<string | null>(null);
const [formData, setFormData] = useState({
firstName: '',
lastName: '',
title: '',
company: '',
email: '',
phone: '',
message: '',
updates: false,
});
const handleInputChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
const { name, value, type, checked } = e.target as any;
setFormData({
...formData,
[name]: type === 'checkbox' ? checked : value,
});
};
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
pageProgressMessage.set('Please wait');
// Placeholder function to send data
console.log('Form data:', formData);
const { response, error } = await httpPost(
`${import.meta.env.PUBLIC_API_URL}/v1-advertise`,
formData,
);
if (!response || error) {
pageProgressMessage.set('');
setError(error?.message || 'Something went wrong. Please try again.');
return;
}
setStatus('submitted');
pageProgressMessage.set('');
}
if (status === 'submitted') {
return (
<div className="flex flex-col items-center justify-center rounded-md border bg-gray-50 p-12 text-center">
<CheckIcon additionalClasses="h-12 w-12 text-green-500 mb-5" />
<h2 className="text-balance text-xl font-semibold text-gray-900">
Thank you for your interest in advertising with roadmap.sh
</h2>
<p className="mt-2 text-sm text-gray-500">
We will get back to you soon.
</p>
</div>
);
}
return (
<>
<h2 className="mb-5 text-balance text-2xl font-bold">
Ready to learn more? Fill out the form below to get started!
</h2>
{error && (
<div className="relative mb-4 rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700">
{error}
</div>
)}
<form className="mb-5" onSubmit={handleSubmit}>
<div className="grid gap-0 sm:grid-cols-2 sm:gap-4">
<Input
label="First Name"
name="firstName"
type="text"
value={formData.firstName}
onChange={handleInputChange}
required
/>
<Input
label="Last Name"
name="lastName"
type="text"
value={formData.lastName}
onChange={handleInputChange}
required
/>
</div>
<div className="grid gap-0 sm:grid-cols-2 sm:gap-4">
<Input
label="Title"
name="title"
type="text"
value={formData.title}
onChange={handleInputChange}
required
/>
<Input
label="Company"
name="company"
type="text"
value={formData.company}
onChange={handleInputChange}
required
/>
</div>
<div className="grid gap-0 sm:grid-cols-2 sm:gap-4">
<Input
label="Email"
name="email"
type="email"
value={formData.email}
onChange={handleInputChange}
required
/>
<Input
label="Phone"
name="phone"
type="tel"
value={formData.phone}
onChange={handleInputChange}
/>
</div>
<Input
label="Message (Optional)"
name="message"
type="textarea"
value={formData.message}
onChange={handleInputChange}
rows={4}
/>
<div className="mb-4 flex items-start">
<div className="flex h-5 items-center">
<input
id="updates"
name="updates"
type="checkbox"
checked={formData.updates}
onChange={handleInputChange}
className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
/>
</div>
<div className="ml-3 text-sm">
<label htmlFor="updates" className="font-medium text-gray-700">
I want to receive occasional updates about new products or
advertising opportunities with roadmap.sh
</label>
</div>
</div>
<div>
<button
type="submit"
className="flex justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
Send
</button>
</div>
</form>
</>
);
}

@ -35,8 +35,8 @@ import Icon from './AstroIcon.astro';
> >
</p> </p>
<div class='flex flex-col justify-between gap-12 sm:flex-row'> <div class='flex flex-col justify-between gap-8 lg:gap-2 lg:flex-row'>
<div class='max-w-[365px]'> <div class='max-w-[425px]'>
<p class='text-md flex items-center'> <p class='text-md flex items-center'>
<a <a
class='inline-flex items-center text-lg font-medium text-white transition-colors hover:text-gray-400' class='inline-flex items-center text-lg font-medium text-white transition-colors hover:text-gray-400'
@ -56,7 +56,7 @@ import Icon from './AstroIcon.astro';
</a> </a>
</p> </p>
<p class='my-4 text-slate-300/60'> <p class='my-4 text-slate-300/60'>
Community created roadmaps, articles, resources and journeys to help Community created roadmaps, best practices, projects, articles, resources and journeys to help
you choose your path and grow in your career. you choose your path and grow in your career.
</p> </p>
<div class='text-sm text-gray-400'> <div class='text-sm text-gray-400'>
@ -67,6 +67,8 @@ import Icon from './AstroIcon.astro';
<span class='mx-1.5'>&middot;</span> <span class='mx-1.5'>&middot;</span>
<a href='/privacy' class='hover:text-white'>Privacy</a> <a href='/privacy' class='hover:text-white'>Privacy</a>
<span class='mx-1.5'>&middot;</span> <span class='mx-1.5'>&middot;</span>
<a href='/advertise' class='hover:text-white'>Advertise</a>
<span class='mx-1.5'>&middot;</span>
<a <a
aria-label='Write us an email' aria-label='Write us an email'
href='mailto:info@roadmap.sh' href='mailto:info@roadmap.sh'
@ -97,20 +99,19 @@ import Icon from './AstroIcon.astro';
</div> </div>
</div> </div>
<div class='max-w-[365px] text-left sm:text-right'> <div class='max-w-[340px] text-left lg:text-right'>
<a href='https://thenewstack.io' target='_blank'> <a href='https://thenewstack.io' target='_blank'>
<img <img
src='/images/tns-sm.png' src='/images/tns-sm.png'
alt='ThewNewStack' alt='ThewNewStack'
class='my-1.5 mr-auto sm:ml-auto sm:mr-0' class='my-1.5 mr-auto lg:ml-auto lg:mr-0'
width='200' width='200'
height='24.8' height='24.8'
loading="lazy" loading="lazy"
/> />
</a> </a>
<p class='my-4 text-slate-300/60'> <p class='my-4 text-slate-300/60'>
The leading DevOps resource for Kubernetes, cloud-native computing, The top DevOps resource for Kubernetes, cloud-native computing, and large-scale development and deployment.
and the latest in at-scale development, deployment, and management.
</p> </p>
<div class='text-sm text-gray-400'> <div class='text-sm text-gray-400'>
<p> <p>

@ -62,6 +62,12 @@ const links = [
Icon: Shirt, Icon: Shirt,
isExternal: true, isExternal: true,
}, },
{
link: '/advertise',
label: 'Advertise',
description: 'Promote your product or service',
Icon: Menu,
},
]; ];
export function NavigationDropdown() { export function NavigationDropdown() {

@ -0,0 +1,39 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import { getRepositoryRank } from '../lib/github.ts';
import { AdvertiseForm } from '../components/AdvertiseForm';
---
<BaseLayout title='About roadmap.sh' permalink={'/about'}>
<div class='bg-white py-8 sm:py-20'>
<div class='container'>
<div class='mb-2 sm:mb-8 flex items-center'>
<div>
<h1 class='mb-0 sm:mb-3 text-2xl font-bold sm:text-4xl'>
Advertise with roadmap.sh
</h1>
<p class='text-lg sm:text-xl text-gray-500'>
The best way to reach developers
</p>
</div>
</div>
<p class='mb-5'>
With hundreds of thousands of monthly visitors and over 1 million
registered users, roadmap.sh is the resource developers choose to skill
up and advance their careers. This community effort creates guides and
educational content where developers can choose their path to success.
</p>
<p class='mb-4 sm:mb-9'>
<span class='font-bold'>roadmap.sh</span> also provides opportunities to
advertise to developers where your message stands out on our platform to
generate valuable results. Do more with your budget and achieve your marketing
goals by targeting your ideal segments of our developer audience. Don’t wait
to get your message in front of aspirational developers.
</p>
<AdvertiseForm client:load />
</div>
</div>
</BaseLayout>
Loading…
Cancel
Save