forked from mantinedev/next-app-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request mantinedev#11 from widgeter/new-components
Include a Contact page
- Loading branch information
Showing
11 changed files
with
446 additions
and
146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import Contact2 from '~/components/widgets/Contact2'; | ||
import Features2 from '~/components/widgets/Features2'; | ||
import { featuresData1 } from '~/shared/data'; | ||
|
||
const Page = () => { | ||
return ( | ||
<> | ||
<Contact2 /> | ||
<Features2 {...featuresData1} /> | ||
</> | ||
); | ||
}; | ||
|
||
export default Page; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
'use client'; | ||
|
||
import { useState } from 'react'; | ||
import { FormProps } from '../../shared/types'; | ||
|
||
const Form = ({ title, description, inputs, radioBtns, textarea, checkboxes, btn, btnPosition }: FormProps) => { | ||
const [inputValues, setInputValues] = useState([]); | ||
const [radioBtnValue, setRadioBtnValue] = useState(''); | ||
const [textareaValues, setTextareaValues] = useState(''); | ||
const [checkedState, setCheckedState] = useState<boolean[]>(new Array(checkboxes && checkboxes.length).fill(false)); | ||
|
||
// Update the value of the entry fields | ||
const changeInputValueHandler = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
const { name, value } = event.target; | ||
|
||
setInputValues({ | ||
...inputValues, | ||
[name]: value, | ||
}); | ||
}; | ||
|
||
// Update checked radio buttons | ||
const changeRadioBtnsHandler = (event: React.ChangeEvent<HTMLInputElement>) => { | ||
setRadioBtnValue(event.target.value); | ||
}; | ||
|
||
// Update the textarea value | ||
const changeTextareaHandler = (event: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
setTextareaValues(event.target.value); | ||
}; | ||
|
||
// Update checkbox radio buttons | ||
const changeCheckboxHandler = (index: number) => { | ||
setCheckedState((prevValues) => { | ||
const newValues = [...(prevValues as boolean[])]; | ||
newValues.map(() => { | ||
newValues[index] = !checkedState[index]; | ||
}); | ||
return newValues; | ||
}); | ||
}; | ||
|
||
return ( | ||
<div className="card h-fit max-w-6xl p-5 md:p-12" id="form"> | ||
{title && <h2 className={`${description ? 'mb-2' : 'mb-4'} text-2xl font-bold`}>{title}</h2>} | ||
{description && <p className="mb-4">{description}</p>} | ||
<form id="contactForm"> | ||
<div className="mb-6"> | ||
{/* Inputs */} | ||
<div className="mx-0 mb-1 sm:mb-4"> | ||
{inputs.map(({ type, label, name, placeholder }, index) => ( | ||
<div key={`item-input-${index}`} className="mx-0 mb-1 sm:mb-4"> | ||
<label htmlFor={name} className="pb-1 text-xs uppercase tracking-wider"> | ||
{label} | ||
</label> | ||
<input | ||
type={type} | ||
name={name} | ||
value={inputValues[index]} | ||
onChange={changeInputValueHandler} | ||
placeholder={placeholder} | ||
className="mb-2 w-full rounded-md border border-gray-400 py-2 pl-2 pr-4 shadow-md dark:text-gray-300 sm:mb-0" | ||
/> | ||
</div> | ||
))} | ||
</div> | ||
{/* Radio buttons */} | ||
{radioBtns && ( | ||
<div className="mx-0 mb-1 sm:mb-3"> | ||
<label className="pb-1 text-xs uppercase tracking-wider">{radioBtns?.label}</label> | ||
<div className="flex flex-wrap"> | ||
{radioBtns.radios.map(({ label }, index) => ( | ||
<div key={`radio-btn-${index}`} className="mr-4 items-baseline"> | ||
<input | ||
type="radio" | ||
name={label} | ||
value={`value${index}`} | ||
checked={radioBtnValue === `value${index}`} | ||
onChange={changeRadioBtnsHandler} | ||
className="cursor-pointer" | ||
/> | ||
<label className="ml-2">{label}</label> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
)} | ||
{/* Textarea */} | ||
{textarea && ( | ||
<div className={`mx-0 mb-1 sm:mb-4`}> | ||
<label htmlFor={textarea.name} className="pb-1 text-xs uppercase tracking-wider"> | ||
{textarea.label} | ||
</label> | ||
<textarea | ||
name={textarea.name} | ||
cols={textarea.cols} | ||
rows={textarea.rows} | ||
value={textareaValues} | ||
onChange={(e) => changeTextareaHandler(e)} | ||
placeholder={textarea.placeholder} | ||
className="mb-2 w-full rounded-md border border-gray-400 py-2 pl-2 pr-4 shadow-md dark:text-gray-300 sm:mb-0" | ||
/> | ||
</div> | ||
)} | ||
{/* Checkboxes */} | ||
{checkboxes && ( | ||
<div className="mx-0 mb-1 sm:mb-4"> | ||
{checkboxes.map(({ label }, index) => ( | ||
<div key={`checkbox-${index}`} className="mx-0 my-1 flex items-baseline"> | ||
<input | ||
type="checkbox" | ||
name={label} | ||
checked={checkedState[index]} | ||
onChange={() => changeCheckboxHandler(index)} | ||
className="cursor-pointer" | ||
/> | ||
<label className="ml-2">{label}</label> | ||
</div> | ||
))} | ||
</div> | ||
)} | ||
</div> | ||
<div | ||
className={`${btnPosition === 'left' ? 'text-left' : btnPosition === 'right' ? 'text-right' : 'text-center'}`} | ||
> | ||
<button type={btn.type} className="btn btn-primary sm:mb-0"> | ||
{btn.title} | ||
</button> | ||
</div> | ||
</form> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Form; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { contact2Data } from '~/shared/data'; | ||
import Form from '../common/Form'; | ||
import HeaderWidget from '../common/HeaderWidget'; | ||
|
||
const Contact2 = () => { | ||
const { header, form } = contact2Data; | ||
|
||
return ( | ||
<section className="bg-primary-50 dark:bg-slate-800" id="contactTwo"> | ||
<div className="mx-auto max-w-6xl px-4 py-16 sm:px-6 lg:px-8 lg:py-20"> | ||
{header && <HeaderWidget header={header} titleClassname="text-3xl sm:text-5xl" />} | ||
<div className="flex items-stretch justify-center"> | ||
<Form {...form} btnPosition="right" /> | ||
</div> | ||
</div> | ||
</section> | ||
); | ||
}; | ||
|
||
export default Contact2; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,29 @@ | ||
import { featuresData } from '~/shared/data'; | ||
import { FeaturesProps } from '~/shared/types'; | ||
import HeaderWidget from '../common/HeaderWidget'; | ||
|
||
const Features = () => { | ||
const { header, items } = featuresData; | ||
|
||
return ( | ||
<section className="scroll-mt-16" id="features"> | ||
<div className="mx-auto max-w-6xl px-4 py-16 lg:px-8 lg:py-20"> | ||
{header && <HeaderWidget header={header} titleClassname="text-4xl md:text-5xl" />} | ||
<div className="mx-auto grid space-y-6 md:grid-cols-2 md:space-y-0"> | ||
{items.map(({ title, description, icon: Icon }, index) => ( | ||
<div key={`item-feature-${index}`} className="space-y-8 sm:px-8"> | ||
<div className="flex md:max-w-md"> | ||
<div className="mb-4 mr-4"> | ||
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary-500 dark:bg-primary-700"> | ||
{Icon && <Icon className="icon-light h-6 w-6 text-white" />} | ||
</div> | ||
</div> | ||
<div className="mb-0 md:mb-8"> | ||
<h3 className="mb-3 text-xl font-bold">{title}</h3> | ||
<p className="text-gray-600 dark:text-slate-400">{description}</p> | ||
const Features = ({ header, items }: FeaturesProps) => ( | ||
<section className="scroll-mt-16" id="features"> | ||
<div className="mx-auto max-w-6xl px-4 py-16 lg:px-8 lg:py-20"> | ||
{header && <HeaderWidget header={header} titleClassname="text-4xl md:text-5xl" />} | ||
<div className="mx-auto grid space-y-6 md:grid-cols-2 md:space-y-0"> | ||
{items.map(({ title, description, icon: Icon }, index) => ( | ||
<div key={`item-feature-${index}`} className="space-y-8 sm:px-8"> | ||
<div className="flex md:max-w-md"> | ||
<div className="mb-4 mr-4"> | ||
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary-500 dark:bg-primary-700"> | ||
{Icon && <Icon className="icon-light h-6 w-6 text-white" />} | ||
</div> | ||
</div> | ||
<div className="mb-0 md:mb-8"> | ||
<h3 className="mb-3 text-xl font-bold">{title}</h3> | ||
<p className="text-gray-600 dark:text-slate-400">{description}</p> | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
))} | ||
</div> | ||
</section> | ||
); | ||
}; | ||
</div> | ||
</section> | ||
); | ||
|
||
export default Features; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,44 @@ | ||
import { featuresData } from '~/shared/data'; | ||
import { Fragment } from 'react'; | ||
import { FeaturesProps } from '~/shared/types'; | ||
import HeaderWidget from '../common/HeaderWidget'; | ||
|
||
const Features2 = () => { | ||
const { header, items } = featuresData; | ||
|
||
return ( | ||
<section className="relative py-16 lg:py-20" id="features2"> | ||
<div className="pointer-events-none absolute inset-0 mb-36 bg-primary-50 dark:bg-slate-800"></div> | ||
<div className="relative mx-auto -mb-12 max-w-6xl px-4 sm:px-6"> | ||
{header && <HeaderWidget header={header} titleClassname="text-4xl md:text-5xl" />} | ||
<div className={`my-12 grid items-stretch gap-6 dark:text-white sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3`}> | ||
{items.map(({ title, description, icon: Icon }, index) => ( | ||
<div | ||
key={`item-feature2-${index}`} | ||
className="relative flex flex-col rounded border border-transparent bg-white p-6 shadow-lg transition hover:shadow-md dark:border-slate-800 dark:bg-slate-900" | ||
> | ||
<div className="flex items-center"> | ||
{Icon && <Icon className="h-10 w-10" />} | ||
<div className="ml-4 text-xl font-bold">{title}</div> | ||
const Features2 = ({ header, items }: FeaturesProps) => ( | ||
<section className="relative py-16 lg:py-20" id="features2"> | ||
<div className="pointer-events-none absolute inset-0 mb-36 bg-primary-50 dark:bg-slate-800"></div> | ||
<div className="relative mx-auto -mb-12 max-w-6xl px-4 sm:px-6"> | ||
{header && <HeaderWidget header={header} titleClassname="text-4xl md:text-5xl" />} | ||
<div | ||
className={`my-12 ${ | ||
items.length > 2 ? 'grid sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3' : 'flex justify-center' | ||
} items-stretch gap-6`} | ||
> | ||
{items.map(({ title, description, icon: Icon, link }, index) => ( | ||
<Fragment key={`item-feature2-${index}`}> | ||
{link ? ( | ||
<a | ||
href={link.href} | ||
className="relative flex min-w-[22em] flex-col rounded border border-transparent bg-white p-6 shadow-lg transition hover:shadow-md dark:border-slate-800 dark:bg-slate-900 dark:text-white dark:shadow-[0_4px_10px_4px_rgba(30,41,59,0.3)]" | ||
> | ||
<div className="flex items-center"> | ||
{Icon && <Icon className="h-10 w-10" />} | ||
<div className="ml-4 text-xl font-bold">{title}</div> | ||
</div> | ||
{description && <p className="text-md mt-4 text-gray-500 dark:text-gray-400">{description}</p>} | ||
</a> | ||
) : ( | ||
<div className="relative flex min-w-[22em] flex-col rounded border border-transparent bg-white p-6 shadow-lg transition hover:shadow-md dark:border-slate-800 dark:bg-slate-900"> | ||
<div className="flex items-center"> | ||
{Icon && <Icon className="h-10 w-10" />} | ||
<div className="ml-4 text-xl font-bold">{title}</div> | ||
</div> | ||
{description && <p className="text-md mt-4 text-gray-500 dark:text-gray-400">{description}</p>} | ||
</div> | ||
{description && <p className="text-md mt-4 text-gray-500 dark:text-gray-400">{description}</p>} | ||
</div> | ||
))} | ||
</div> | ||
)} | ||
</Fragment> | ||
))} | ||
</div> | ||
</section> | ||
); | ||
}; | ||
</div> | ||
</section> | ||
); | ||
|
||
export default Features2; |
Oops, something went wrong.