fix contact form
Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
parent
b3d3443243
commit
d85a29c15d
10
actions/contact.ts
Normal file
10
actions/contact.ts
Normal file
@ -0,0 +1,10 @@
|
||||
"use server";
|
||||
|
||||
export default async function contactForm(formData: FormData) {
|
||||
const rawFormData = {
|
||||
name: formData.get('name'),
|
||||
email: formData.get('email'),
|
||||
message: formData.get('message'),
|
||||
};
|
||||
console.log(rawFormData);
|
||||
};
|
@ -1,122 +0,0 @@
|
||||
import React from 'react';
|
||||
import { User, Award, Globe } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { allAuthors } from '@/.content-collections/generated';
|
||||
import Image from 'next/image';
|
||||
|
||||
const TeamMember = ({ name, role, image }) => (
|
||||
<div className="text-center">
|
||||
<Image className="mx-auto h-40 w-40 rounded-full" width={256} height={256} src={image} alt={name} />
|
||||
<div className="mt-4">
|
||||
<h3 className="text-lg font-medium text-gray-900">{name}</h3>
|
||||
<p className="text-sm text-gray-500">{role}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
function shuffle(array) {
|
||||
let currentIndex = array.length;
|
||||
|
||||
// While there remain elements to shuffle...
|
||||
while (currentIndex != 0) {
|
||||
|
||||
// Pick a remaining element...
|
||||
let randomIndex = Math.floor(Math.random() * currentIndex);
|
||||
currentIndex--;
|
||||
|
||||
// And swap it with the current element.
|
||||
[array[currentIndex], array[randomIndex]] = [
|
||||
array[randomIndex], array[currentIndex]];
|
||||
}
|
||||
}
|
||||
|
||||
const AboutPage = () => {
|
||||
const teamMembers = allAuthors.map(author => ({
|
||||
name: author.displayName,
|
||||
role: author.role,
|
||||
image: author.avatarUrl,
|
||||
}));
|
||||
shuffle(teamMembers);
|
||||
|
||||
return (
|
||||
<div className="bg-gray-100 min-h-screen">
|
||||
<header className="bg-white shadow">
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-3xl font-bold text-gray-900">About Us</h1>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<div className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
|
||||
<div className="px-4 py-6 sm:px-0">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-extrabold text-gray-900 sm:text-4xl">
|
||||
Empowering Canadian Businesses with Innovative Technology
|
||||
</h2>
|
||||
<p className="mt-4 text-xl text-gray-500">
|
||||
Techaro Computing Canada is at the forefront of digital transformation, helping businesses across the country leverage cutting-edge technology to drive growth and innovation.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white shadow overflow-hidden sm:rounded-lg mb-12">
|
||||
<div className="px-4 py-5 sm:px-6">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900">Our Mission</h3>
|
||||
</div>
|
||||
<div className="border-t border-gray-200">
|
||||
<dl>
|
||||
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm font-medium text-gray-500 flex items-center">
|
||||
<User className="h-5 w-5 mr-2 text-blue-500" />
|
||||
Client Focus
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
We are dedicated to understanding and meeting the unique needs of each client, ensuring their success in the digital landscape.
|
||||
</dd>
|
||||
</div>
|
||||
<div className="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm font-medium text-gray-500 flex items-center">
|
||||
<Award className="h-5 w-5 mr-2 text-blue-500" />
|
||||
Innovation
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
We continuously explore and implement the latest technologies to provide cutting-edge solutions for our clients.
|
||||
</dd>
|
||||
</div>
|
||||
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm font-medium text-gray-500 flex items-center">
|
||||
<Globe className="h-5 w-5 mr-2 text-blue-500" />
|
||||
Canadian Focus
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
We are committed to strengthening the Canadian tech ecosystem and helping local businesses compete on a global scale.
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center mb-12">
|
||||
<h3 className="text-2xl font-bold text-gray-900">Our Team</h3>
|
||||
<div className="mt-10 grid grid-cols-1 gap-10 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{teamMembers.map((member, index) => (
|
||||
<TeamMember key={index} {...member} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-blue-700 rounded-lg shadow-xl overflow-hidden">
|
||||
<div className="px-4 py-5 sm:p-6 text-center">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">Ready to Transform Your Business?</h3>
|
||||
<p className="text-blue-100 mb-6">Let{"'"}s discuss how Techaro Computing Canada can help you achieve your technology goals.</p>
|
||||
<Button className="bg-white text-blue-700 hover:bg-blue-50">
|
||||
Schedule a Consultation
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AboutPage;
|
155
app/about/page.tsx
Normal file
155
app/about/page.tsx
Normal file
@ -0,0 +1,155 @@
|
||||
import React from "react";
|
||||
import { User, Award, Globe } from "lucide-react";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { allAuthors } from "@/.content-collections/generated";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
const TeamMember = ({
|
||||
name,
|
||||
role,
|
||||
image,
|
||||
}: {
|
||||
name: string;
|
||||
role: string;
|
||||
image: string;
|
||||
}) => (
|
||||
<div className="text-center">
|
||||
<Image
|
||||
className="mx-auto h-40 w-40 rounded-full"
|
||||
width={256}
|
||||
height={256}
|
||||
src={image}
|
||||
alt={name}
|
||||
/>
|
||||
<div className="mt-4">
|
||||
<h3 className="text-lg font-medium text-gray-900">{name}</h3>
|
||||
<p className="text-sm text-gray-500">{role}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
function shuffle(array: any[]) {
|
||||
let currentIndex = array.length;
|
||||
|
||||
// While there remain elements to shuffle...
|
||||
while (currentIndex != 0) {
|
||||
// Pick a remaining element...
|
||||
let randomIndex = Math.floor(Math.random() * currentIndex);
|
||||
currentIndex--;
|
||||
|
||||
// And swap it with the current element.
|
||||
[array[currentIndex], array[randomIndex]] = [
|
||||
array[randomIndex],
|
||||
array[currentIndex],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
const AboutPage = () => {
|
||||
const teamMembers = allAuthors.map((author) => ({
|
||||
name: author.displayName,
|
||||
role: author.role,
|
||||
image: author.avatarUrl,
|
||||
}));
|
||||
shuffle(teamMembers);
|
||||
|
||||
return (
|
||||
<div className="bg-gray-100 min-h-screen">
|
||||
<header className="bg-white shadow">
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-3xl font-bold text-gray-900">About Us</h1>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<div className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
|
||||
<div className="px-4 py-6 sm:px-0">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-extrabold text-gray-900 sm:text-4xl">
|
||||
Empowering Canadian Businesses with Innovative Technology
|
||||
</h2>
|
||||
<p className="mt-4 text-xl text-gray-500">
|
||||
Techaro Computing Canada is at the forefront of digital
|
||||
transformation, helping businesses across the country leverage
|
||||
cutting-edge technology to drive growth and innovation.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white shadow overflow-hidden sm:rounded-lg mb-12">
|
||||
<div className="px-4 py-5 sm:px-6">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
||||
Our Mission
|
||||
</h3>
|
||||
</div>
|
||||
<div className="border-t border-gray-200">
|
||||
<dl>
|
||||
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm font-medium text-gray-500 flex items-center">
|
||||
<User className="h-5 w-5 mr-2 text-blue-500" />
|
||||
Client Focus
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
We are dedicated to understanding and meeting the unique
|
||||
needs of each client, ensuring their success in the
|
||||
digital landscape.
|
||||
</dd>
|
||||
</div>
|
||||
<div className="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm font-medium text-gray-500 flex items-center">
|
||||
<Award className="h-5 w-5 mr-2 text-blue-500" />
|
||||
Innovation
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
We continuously explore and implement the latest
|
||||
technologies to provide cutting-edge solutions for our
|
||||
clients.
|
||||
</dd>
|
||||
</div>
|
||||
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm font-medium text-gray-500 flex items-center">
|
||||
<Globe className="h-5 w-5 mr-2 text-blue-500" />
|
||||
Canadian Focus
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
We are committed to strengthening the Canadian tech
|
||||
ecosystem and helping local businesses compete on a global
|
||||
scale.
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center mb-12">
|
||||
<h3 className="text-2xl font-bold text-gray-900">Our Team</h3>
|
||||
<div className="mt-10 grid grid-cols-1 gap-10 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{teamMembers.map((member, index) => (
|
||||
<TeamMember key={index} {...member} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-blue-700 rounded-lg shadow-xl overflow-hidden">
|
||||
<div className="px-4 py-5 sm:p-6 text-center">
|
||||
<h3 className="text-2xl font-semibold text-white mb-4">
|
||||
Ready to Transform Your Business?
|
||||
</h3>
|
||||
<p className="text-blue-100 mb-6">
|
||||
Let{"'"}s discuss how Techaro Computing Canada can help you
|
||||
achieve your technology goals.
|
||||
</p>
|
||||
<Link href="/contact">
|
||||
<Button className="bg-white text-blue-700 hover:bg-blue-50">
|
||||
Schedule a Consultation
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AboutPage;
|
@ -36,10 +36,10 @@ export default async function Page({ params }: { params: PageParams }) {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<p className="text-muted-foreground pb-8 mt-4 text-sm max-w-[80ch] mx-auto">
|
||||
<div className="text-muted-foreground pb-8 mt-4 text-sm max-w-[80ch] mx-auto">
|
||||
<AuthorChip {...page.author!} />
|
||||
{page.summary}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{page.image !== undefined && (
|
||||
<Image
|
||||
|
@ -1,51 +1,62 @@
|
||||
import React from 'react';
|
||||
"use client";
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import contactForm from '@/actions/contact';
|
||||
|
||||
const ContactPage = () => {
|
||||
async function contactForm(formData) {
|
||||
"use server";
|
||||
const rawFormData = {
|
||||
name: formData.get('name'),
|
||||
email: formData.get('email'),
|
||||
message: formData.get('message'),
|
||||
};
|
||||
console.log(rawFormData);
|
||||
};
|
||||
const [message, setMessage] = useState(null);
|
||||
|
||||
const callback = async (formData) => {
|
||||
await contactForm(formData);
|
||||
setMessage("Our intrepid team of code monkeys will be looking at this as soon as possible!");
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-gray-100 mx-auto text-gray-900 px-4 pt-8">
|
||||
<h1 className="text-3xl font-bold text-gray-900 mb-6">Contact Techaro Computing Canada</h1>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div className="text-gray-900">
|
||||
<h2 className="text-xl font-semibold mb-4">Get in Touch</h2>
|
||||
<p className="mb-4">We would love to hear from you. Please fill out the form below or use our contact information.</p>
|
||||
|
||||
<h3 className="text-lg font-semibold mb-2">Contact Information</h3>
|
||||
<p>Email: sales@techaro.lol</p>
|
||||
<p>Phone: (123) 456-7890</p>
|
||||
<p>Address: 123 Tech Street, Toronto, ON M5V 1J2</p>
|
||||
<>
|
||||
<header className="bg-white shadow">
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-3xl font-bold text-gray-900">Contact Us</h1>
|
||||
</div>
|
||||
</header>
|
||||
<div className="bg-gray-100 mx-auto text-gray-900 px-4 pt-8">
|
||||
<div className="grid grid-cols-1 gap-8 max-w-3xl mx-auto">
|
||||
<div className="text-gray-900">
|
||||
<h2 className="text-xl font-semibold mb-4">Get in Touch</h2>
|
||||
<p className="mb-4">We would love to hear from you. Please fill out the form below or use our contact information.</p>
|
||||
|
||||
<div className="pb-4">
|
||||
<h2 className="text-xl font-semibold mb-4">Contact Form</h2>
|
||||
<form className="space-y-4" action={contactForm}>
|
||||
<div>
|
||||
<label htmlFor="name" className="block mb-1">Name</label>
|
||||
<input disabled type="text" id="name" name="name" className="w-full px-3 py-2 border rounded" required />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="email" className="block mb-1">Email</label>
|
||||
<input disabled type="email" id="email" name="email" className="w-full px-3 py-2 border rounded" required />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="message" className="block mb-1">Message</label>
|
||||
<textarea disabled id="message" name="message" rows="4" className="w-full px-3 py-2 border rounded" required></textarea>
|
||||
</div>
|
||||
<button type="submit" disabled className="bg-gray-500 text-white px-4 py-2 rounded hover:bg-gray-600">Send Message</button>
|
||||
</form>
|
||||
<h3 className="text-lg font-semibold mb-2">Contact Information</h3>
|
||||
<p>Email: sales@techaro.lol</p>
|
||||
</div>
|
||||
|
||||
<div className="pb-4">
|
||||
<h2 className="text-xl font-semibold mb-4">Contact Form</h2>
|
||||
<form className="space-y-4" action={callback}>
|
||||
<div>
|
||||
<label htmlFor="name" className="block mb-1">Name</label>
|
||||
<input type="text" id="name" name="name" className="w-full px-3 py-2 border rounded" required />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="email" className="block mb-1">Email</label>
|
||||
<input type="email" id="email" name="email" className="w-full px-3 py-2 border rounded" required />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="message" className="block mb-1">Message</label>
|
||||
<textarea id="message" name="message" rows="4" className="w-full px-3 py-2 border rounded" required></textarea>
|
||||
</div>
|
||||
<button type="submit" className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">Send Message</button>
|
||||
{message !== null && (
|
||||
<>
|
||||
<div className="p-4 bg-gray-200">
|
||||
<p className="text-xl">Thanks!</p>
|
||||
<p className="p-4">{message}</p>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,7 @@ const authors = defineCollection({
|
||||
schema: (z) => ({
|
||||
name: z.string(),
|
||||
displayName: z.string(),
|
||||
active: z.boolean().default(true),
|
||||
role: z.string(),
|
||||
avatarUrl: z.string(),
|
||||
bluesky: z.string().optional(),
|
||||
|
@ -4,4 +4,5 @@ displayName: "Mimi Yasomi"
|
||||
role: "Member of Technical Staff"
|
||||
avatarUrl: /img/avatars/mimi.webp
|
||||
bluesky: yasomi.xeiaso.net
|
||||
active: true
|
||||
---
|
||||
|
Loading…
x
Reference in New Issue
Block a user