mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-09-02 13:52:46 +02:00
Add advertisement page
This commit is contained in:
227
src/components/AdvertiseForm.tsx
Normal file
227
src/components/AdvertiseForm.tsx
Normal file
@@ -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>
|
||||
|
||||
<div class='flex flex-col justify-between gap-12 sm:flex-row'>
|
||||
<div class='max-w-[365px]'>
|
||||
<div class='flex flex-col justify-between gap-8 lg:gap-2 lg:flex-row'>
|
||||
<div class='max-w-[425px]'>
|
||||
<p class='text-md flex items-center'>
|
||||
<a
|
||||
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>
|
||||
</p>
|
||||
<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.
|
||||
</p>
|
||||
<div class='text-sm text-gray-400'>
|
||||
@@ -67,6 +67,8 @@ import Icon from './AstroIcon.astro';
|
||||
<span class='mx-1.5'>·</span>
|
||||
<a href='/privacy' class='hover:text-white'>Privacy</a>
|
||||
<span class='mx-1.5'>·</span>
|
||||
<a href='/advertise' class='hover:text-white'>Advertise</a>
|
||||
<span class='mx-1.5'>·</span>
|
||||
<a
|
||||
aria-label='Write us an email'
|
||||
href='mailto:info@roadmap.sh'
|
||||
@@ -97,20 +99,19 @@ import Icon from './AstroIcon.astro';
|
||||
</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'>
|
||||
<img
|
||||
src='/images/tns-sm.png'
|
||||
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'
|
||||
height='24.8'
|
||||
loading="lazy"
|
||||
/>
|
||||
</a>
|
||||
<p class='my-4 text-slate-300/60'>
|
||||
The leading DevOps resource for Kubernetes, cloud-native computing,
|
||||
and the latest in at-scale development, deployment, and management.
|
||||
The top DevOps resource for Kubernetes, cloud-native computing, and large-scale development and deployment.
|
||||
</p>
|
||||
<div class='text-sm text-gray-400'>
|
||||
<p>
|
||||
|
@@ -62,6 +62,12 @@ const links = [
|
||||
Icon: Shirt,
|
||||
isExternal: true,
|
||||
},
|
||||
{
|
||||
link: '/advertise',
|
||||
label: 'Advertise',
|
||||
description: 'Promote your product or service',
|
||||
Icon: Menu,
|
||||
},
|
||||
];
|
||||
|
||||
export function NavigationDropdown() {
|
||||
|
39
src/pages/advertise.astro
Normal file
39
src/pages/advertise.astro
Normal file
@@ -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>
|
Reference in New Issue
Block a user