Skip to content

Commit

Permalink
added products and contact page
Browse files Browse the repository at this point in the history
  • Loading branch information
kumar Saurabh committed Apr 4, 2022
1 parent fa33337 commit cb9d6c4
Show file tree
Hide file tree
Showing 11 changed files with 317 additions and 6 deletions.
1 change: 1 addition & 0 deletions .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"@components": "./src/components",
"@libs": "./src/libs",
"@pages": "./src/pages",
"@data": "./src/data",
"@svg": "./public/svg"
}
}
Expand Down
Binary file added public/assets/asset.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/car.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/obd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/truck.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
224 changes: 224 additions & 0 deletions src/components/Contact.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import React, { useState } from "react";
import ButtonPrimary from "@components/misc/ButtonPrimary"

export default function Contact() {
const [fullname, setFullname] = useState("");
const [email, setEmail] = useState("");
const [subject, setSubject] = useState("");
const [message, setMessage] = useState("");

// Form validation
const [errors, setErrors] = useState({});

// Setting button text
const [buttonText, setButtonText] = useState("Send");

const [showSuccessMessage, setShowSuccessMessage] = useState(false);
const [showFailureMessage, setShowFailureMessage] = useState(false);

const handleValidation = () => {
let tempErrors = {};
let isValid = true;

if (fullname.length <= 0) {
tempErrors["fullname"] = true;
isValid = false;
}
if (email.length <= 0) {
tempErrors["email"] = true;
isValid = false;
}
if (subject.length <= 0) {
tempErrors["subject"] = true;
isValid = false;
}
if (message.length <= 0) {
tempErrors["message"] = true;
isValid = false;
}

setErrors({ ...tempErrors });
console.log("errors", errors);
return isValid;
};

// const [form, setForm] = useState(false);

const handleSubmit = async (e) => {
e.preventDefault();

let isValidForm = handleValidation();

if (isValidForm) {
setButtonText("Sending");
const res = await fetch("/api/sendgrid", {
body: JSON.stringify({
email: email,
fullname: fullname,
subject: subject,
message: message,
}),
headers: {
"Content-Type": "application/json",
},
method: "POST",
});

const { error } = await res.json();
if (error) {
console.log(error);
setShowSuccessMessage(false);
setShowFailureMessage(true);
setButtonText("Send");

// Reset form fields
setFullname("");
setEmail("");
setMessage("");
setSubject("");
return;
}
setShowSuccessMessage(true);
setShowFailureMessage(false);
setButtonText("Send");
// Reset form fields
setFullname("");
setEmail("");
setMessage("");
setSubject("");
}
console.log(fullname, email, subject, message);
};
return (
<header className="p-8 grid grid-cols-1 md:grid-cols-2 gap-4 pt-10 lg:px-40 bg-blue-50 dark:bg-blue-900 md:h-144">
<div className="mx-auto mb-10 md:mt-20">
<div className="badge bg-orange-500 inline-block rounded-xl">
<p className="font-light text-base px-4 py-1 text-white-300">
Lets talk
</p>
</div>
<h1 className="text-4xl font-bold mt-4 dark:text-gray-50 text-gray-700">
Lets talk about your requirements.
</h1>
<p className="text-sm text-gray-700 mt-4 font-light dark:text-gray-200">
Fill the form and send in your queries. I will respond as soon as I
can. Alternatively, You can reach out to me at my email address/mobile.
</p>
</div>
<form
onSubmit={handleSubmit}
className="rounded-lg shadow-lg flex flex-col px-8 py-8 bg-white dark:bg-blue-500"
>
<h1 className="text-2xl font-bold dark:text-gray-50">
Send a message
</h1>

<label
htmlFor="fullname"
className="text-gray-400 font-light mt-8 dark:text-gray-50"
>
Full name<span className="text-red-400 dark:text-gray-50">*</span>
</label>
<input
type="text"
value={fullname}
onChange={(e) => {
setFullname(e.target.value);
}}
name="fullname"
className="bg-transparent border-b py-2 pl-4 focus:outline-none focus:rounded-md focus:ring-1 ring-orange-500 font-light text-gray-400"
/>
{errors?.fullname && (
<p className="text-red-500">Fullname cannot be empty.</p>
)}

<label
htmlFor="email"
className="text-gray-400 font-light mt-4 dark:text-gray-50"
>
E-mail<span className="text-red-400">*</span>
</label>
<input
type="email"
name="email"
value={email}
onChange={(e) => {
setEmail(e.target.value);
}}
className="bg-transparent border-b py-2 pl-4 focus:outline-none focus:rounded-md focus:ring-1 ring-orange-500 font-light text-gray-400"
/>
{errors?.email && (
<p className="text-red-500">Email cannot be empty.</p>
)}

<label
htmlFor="subject"
className="text-gray-400 font-light mt-4 dark:text-gray-50"
>
Subject<span className="text-red-400">*</span>
</label>
<input
type="text"
name="subject"
value={subject}
onChange={(e) => {
setSubject(e.target.value);
}}
className="bg-transparent border-b py-2 pl-4 focus:outline-none focus:rounded-md focus:ring-1 ring-orange-500 font-light text-gray-400"
/>
{errors?.subject && (
<p className="text-red-500">Subject cannot be empty.</p>
)}
<label
htmlFor="message"
className="text-gray-400 font-light mt-4 dark:text-gray-50"
>
Message<span className="text-red-400">*</span>
</label>
<textarea
name="message"
value={message}
onChange={(e) => {
setMessage(e.target.value);
}}
className="bg-transparent border-b py-2 pl-4 focus:outline-none focus:rounded-md focus:ring-1 ring-orange-500 font-light text-gray-400"
></textarea>
{errors?.message && (
<p className="text-red-500">Message body cannot be empty.</p>
)}
<div className="flex flex-row items-center justify-start mt-8">
<ButtonPrimary
type="submit"
>
{buttonText}
<svg
width="24"
height="24"
viewBox="0 0 24 24"
className="text-cyan-500 ml-2"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.00967 5.12761H11.0097C12.1142 5.12761 13.468 5.89682 14.0335 6.8457L16.5089 11H21.0097C21.562 11 22.0097 11.4477 22.0097 12C22.0097 12.5523 21.562 13 21.0097 13H16.4138L13.9383 17.1543C13.3729 18.1032 12.0191 18.8724 10.9145 18.8724H8.91454L12.4138 13H5.42485L3.99036 15.4529H1.99036L4.00967 12L4.00967 11.967L2.00967 8.54712H4.00967L5.44417 11H12.5089L9.00967 5.12761Z"
fill="currentColor"
/>
</svg>
</ButtonPrimary>
</div>
<div className="text-left">
{showSuccessMessage && (
<p className="text-green-500 font-semibold text-sm my-2">
Thankyou! Your Message has been delivered.
</p>
)}
{showFailureMessage && (
<p className="text-red-500">
Oops! Something went wrong, please try again.
</p>
)}
</div>
</form>
</header>
);
}
47 changes: 47 additions & 0 deletions src/components/Product.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import Image from "next/image";
import React from "react";
import ButtonPrimary from "@components/misc/ButtonPrimary";

const Product = ({ product }) => {
const features = product.features.split('|')
const contentSection = <div className="flex flex-col items-end justify-center ml-auto w-full lg:w-9/12">
<h3 className="text-3xl lg:text-4xl font-medium leading-relaxed text-black-600">
{product.name}
</h3>
<p className="my-2 text-black-500">
{product.desc}
</p>
<ul className="text-black-500 self-start list-inside ml-8">
{features.map(feature => <li className="relative circle-check custom-list mb-2">
{feature}
</li>)}
</ul>
</div>

const imageSection = <div className="flex w-full justify-end">
<div className="h-full w-full p-4">
<Image
src={`/assets/${product.image}.png`}
alt={product.name}
layout="responsive"
quality={100}
height={414}
width={508}
/>
<div className="flex justify-center mt-5"><ButtonPrimary>Explore More</ButtonPrimary></div>
</div>
</div >

return (
<div
className="max-w-screen-xl mt-8 mb-6 sm:mt-14 sm:mb-14 px-6 sm:px-8 lg:px-16 mx-auto"
>
<div className="grid grid-flow-row sm:grid-flow-col grid-cols-1 sm:grid-cols-2 gap-8 py-8 my-12">
{product.orientation === 'left' ? contentSection : imageSection}
{product.orientation === 'left' ? imageSection : contentSection}
</div>
</div>
);
};

export default Product;
2 changes: 1 addition & 1 deletion src/components/misc/ButtonPrimary.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const ButtonPrimary = ({ children, addClass }) => {
return (
<button
className={
"py-3 lg:py-4 px-12 lg:px-16 text-white-500 font-semibold rounded-lg bg-orange-500 hover:shadow-orange-md transition-all outline-none " +
"flex py-3 lg:py-4 px-12 lg:px-16 text-white-500 font-semibold rounded-lg bg-orange-500 hover:shadow-orange-md transition-all outline-none " +
addClass
}
>
Expand Down
37 changes: 37 additions & 0 deletions src/data/products.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[
{
"name": "EV02-Vehicle GPS Tracker",
"desc": "EV02 is a four wires real-time positioning device that can implement function such as electronic fences, remote tracking, and one-click car locks. The GPS can meet the needs of scenarios such as car monitoring, online car-hailing, car rental, and cargo logistics and transportation",
"orientation": "right",
"image": "illustration2",
"features": "Remotely cut-off petrol/electricity|GNSS second fast positioning|Platform/APP/SMS checking|Mini size, easy to install"
},
{
"name": "MT100-Vehicle GPS Tracker",
"desc": "MT100 is a compact GPS tracker for vehicles, it is small in size and with internal GPS/ GSM antenna.It is designed for cars, vehicles, scooters and motorcycles, the device itself supports 9 - 90 volts, and it has one digital output for power off relay connecting and one digital input for ignition detect and Bluetooth function, etc.",
"orientation": "left",
"image": "obd",
"features": "Support GPS, AGPS and LBS, super-fast and accurate positioning|Supports GPS/LBS/AGPS positioning|Support upload interval by time, distance and speed|Built in high sensitive G-sensor accelerometer real-time GPS tracking, history playback, blind data storage, cornering compensation.Built in light sensor for removal alarm|Driving behavior monitor (speeding, harsh deceleration, harsh acceleration, cornering alarm)|9-90 Wide voltage & dual IP supported (main server and backup server)."
},
{
"name": "V7-Vehicle GPS Tracker",
"desc": "This GPS vehicle tracker is designed to meet the needs of various peripherals. Its wide voltage range ensures its stable running on electromobiles, motorcycles, cars and trucks. Small but compact, its highly reliable electric circuit and internal battery designfunctions not only basic tracking butSOS call, tele-cutoff fuel, geo-fence, overspeedalert, historical data upload and more.",
"orientation": "right",
"image": "asset",
"features": "Remote cut-off (petrol/power) Compel the vehicle to stop by breaking off the fuel connection|IP65 dust and water proof Water-resistant case & cable ensure stable operation in tough environment|ACC detection for lgnition status Be aware of the igniton status whenever you need|9-90V voltage range Wide operating voltage applicable to all types of vehicles|Multiple alarms Instant alert for vibration, overspeed, power off, geo-fence|Vehicle battery protection Never drain out of the battery of moforcycle for optimal protection"
},
{
"name": "V5-Vehicle GPS Tracker",
"desc": "This GPS vehicle tracker is designed to meet the needs of various peripherals. Its wide voltage range ensures its stable running on electromobiles, motorcycles, cars and trucks. Small but compact, its highly reliable electric circuit and internal battery designfunctions not only basic tracking butSOS call, tele-cutoff fuel, geo-fence, overspeedalert, historical data upload and more.",
"orientation": "left",
"image": "car",
"features": "Remote cut-off (petrol/power) Compel the vehicle to stop by breaking off the fuel connection|IP65 dust and water proof Water-resistant case & cable ensure stable operation in tough environment|ACC detection for lgnition status Be aware of the igniton status whenever you need|9-90V voltage range Wide operating voltage applicable to all types of vehicles|Multiple alarms Instant alert for vibration, overspeed, power off, geo-fence|Vehicle battery protection Never drain out of the battery of moforcycle for optimal protection"
},
{
"name": "TK003-Vehicle GPS Tracker",
"desc": "This GPS vehicle tracker is designed to meet the needs of various peripherals. Its wide voltage range ensures its stable running on electromobiles, motorcycles, cars and trucks. Small but compact, its highly reliable electric circuit and internal battery designfunctions not only basic tracking butSOS call, tele-cutoff fuel, geo-fence, overspeedalert, historical data upload and more.",
"orientation": "right",
"image": "car",
"features": "Remote cut-off (petrol/power) Compel the vehicle to stop by breaking off the fuel connection|IP65 dust and water proof Water-resistant case & cable ensure stable operation in tough environment|ACC detection for lgnition status Be aware of the igniton status whenever you need|9-90V voltage range Wide operating voltage applicable to all types of vehicles|Multiple alarms Instant alert for vibration, overspeed, power off, geo-fence|Vehicle battery protection Never drain out of the battery of moforcycle for optimal protection"
}
]
7 changes: 4 additions & 3 deletions src/pages/contact/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import Head from 'next/head'
import React from 'react'
import Seo from '@components/Seo'
import Contact from '@components/Contact'

function Contact() {
function ContactPage() {
return (
<>
<Seo title='Contact - Pathways Telematics' />
<h1>Contact page</h1>
<Contact />
</>
)
}

export default Contact
export default ContactPage
5 changes: 3 additions & 2 deletions src/pages/products/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react'
import Seo from '@components/Seo'

import Product from '@components/Product'
import products from '@data/products.json'
function Products() {
return (
<>
<Seo title='Products - Pathways Telematics' />
<h1>Products Page</h1>
{products.map(product => <Product product={product} />)}
</>
)
}
Expand Down

0 comments on commit cb9d6c4

Please sign in to comment.