Browse Source

refactor: added hover card and contact page

hover-contact
Lazar Kostic 3 years ago
parent
commit
10a1ff3861

+ 37
- 0
components/cards/hover-image-card/hover-image-card.js View File

@@ -0,0 +1,37 @@
import styles from './hover-image-card.module.css';

const HoverImageCard = () => {
return (
<div className={styles.container}>
<div className={styles.card}>
<div className={styles.content}>
<p>Next JS Path</p>
<p>18-8-2022</p>
<button className={styles.btn}>More Details</button>
</div>
{/*Change with Next Image*/}
<img src="/images/image-one.jpg" alt="text" />
</div>
<div className={styles.card}>
<div className={styles.content}>
<p>Text 1</p>
<p>Text 2</p>
<button className={styles.btn}>Button Text</button>
</div>
{/*Change with Next Image*/}
<img src="/images/image-one.jpg" alt="text" />
</div>
<div className={styles.card}>
<div className={styles.content}>
<p>Text 1</p>
<p>Text 2</p>
<button className={styles.btn}>Button Text</button>
</div>
{/*Change with Next Image*/}
<img src="/images/image-one.jpg" alt="text" />
</div>
</div>
);
};

export default HoverImageCard;

+ 75
- 0
components/cards/hover-image-card/hover-image-card.module.css View File

@@ -0,0 +1,75 @@
.container {
display: flex;
justify-content: center;
margin-top: 30px;
}

.card {
position: relative;
width: 230px;
height: 260px;
margin: 0 5px;
background-color: red;
transition: 0.3s;
overflow: hidden;
cursor: pointer;
}

.card img {
width: 100%;
height: 100%;
object-fit: cover;
transition: 0.3s;
}

.card::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: 0.3s;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1));
}

.content {
position: absolute;
bottom: 0;
width: 100%;
padding: 1rem;
z-index: 1;
color: #fff;
transition: 0.3s;
opacity: 0;
}

.btn {
padding: 0.3rem 0.8rem;
font-size: 0.6rem;
border: none;
cursor: pointer;
outline: none;
color: #fff;
background: transparent;
border: 2px solid #fff;
}

.content p {
font-size: 0.6rem;
margin: 0.5rem 0;
}

.card:hover {
width: 350px;
}

.card:hover img {
transform: scale(1.1);
}

.card:hover:after,
.card:hover .content {
opacity: 1;
}

+ 118
- 0
components/forms/contact/ContactForm.jsx View File

@@ -0,0 +1,118 @@
import {
Box,
Button,
Container,
Grid,
TextField,
Typography
} from '@mui/material';
import { useFormik } from 'formik';
import { useTranslation } from 'next-i18next';
import Link from 'next/link';
import React from 'react';
import { BASE_PAGE } from '../../../constants/pages';
import { contactSchema } from '../../../schemas/contactSchema';
const ContactForm = () => {
const { t } = useTranslation('forms', 'contact', 'common');
const handleSubmit = (values) => {
console.log('Values', values);
};
const formik = useFormik({
initialValues: {
firstName: '',
lastName: '',
email: '',
message: ''
},
validationSchema: contactSchema,
onSubmit: handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});
return (
<Container component="main" maxWidth="md">
<Box
sx={{
marginTop: 32,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Typography component="h1" variant="h5">
{t('contact:Title')}
</Typography>
<Box
component="form"
onSubmit={formik.handleSubmit}
sx={{ position: 'relative', mt: 1, p: 1 }}
>
<TextField
name="firstName"
label={t('forms:FirstName')}
margin="normal"
value={formik.values.firstName}
onChange={formik.handleChange}
error={formik.touched.firstName && Boolean(formik.errors.firstName)}
helperText={formik.touched.firstName && formik.errors.firstName}
autoFocus
fullWidth
/>
<TextField
name="lastName"
label={t('forms:LastName')}
margin="normal"
value={formik.values.lastName}
onChange={formik.handleChange}
error={formik.touched.lastName && Boolean(formik.errors.lastName)}
helperText={formik.touched.lastName && formik.errors.lastName}
autoFocus
fullWidth
/>
<TextField
name="email"
label={t('forms:Email')}
margin="normal"
value={formik.values.email}
onChange={formik.handleChange}
error={formik.touched.email && Boolean(formik.errors.email)}
helperText={formik.touched.email && formik.errors.email}
autoFocus
fullWidth
/>
<TextField
name="message"
label={t('forms:Message')}
multiline
margin="normal"
value={formik.values.message}
onChange={formik.handleChange}
error={formik.touched.message && Boolean(formik.errors.message)}
helperText={formik.touched.message && formik.errors.message}
rows={4}
autoFocus
fullWidth
/>
<Button
type="submit"
variant="contained"
sx={{ mt: 3, mb: 2 }}
fullWidth
>
{t('contact:SendBtn')}
</Button>
<Grid container justifyContent="center">
<Link href={BASE_PAGE}>{t('common:Back')}</Link>
</Grid>
</Box>
</Box>
</Container>
);
};
export default ContactForm;

+ 16
- 0
pages/contact.js View File

@@ -0,0 +1,16 @@
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import ContactForm from '../components/forms/contact/ContactForm';

const ContactPage = () => {
return <ContactForm />;
};

export async function getStaticProps({ locale }) {
return {
props: {
...(await serverSideTranslations(locale, ['forms', 'contact', 'common'])),
},
};
}

export default ContactPage;

+ 2
- 0
pages/index.js View File

@@ -1,6 +1,7 @@
import { dehydrate, QueryClient } from '@tanstack/react-query';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import Head from 'next/head';
import HoverImageCard from '../components/cards/hover-image-card/hover-image-card';
import PaginationComponentRQ from '../components/pagination/react-query/PaginationComponentRQ';
import { getData } from '../requests/dataRequest';

@@ -12,6 +13,7 @@ const Home = () => {
<meta name="description" content="Random data with pagination..." />
</Head>
<PaginationComponentRQ></PaginationComponentRQ>
<HoverImageCard />
</>
);
};

BIN
public/images/image-one.jpg View File


+ 4
- 0
public/locales/en/contact.json View File

@@ -0,0 +1,4 @@
{
"Title": "Contact",
"SendBtn": "Submit"
}

+ 3
- 0
public/locales/en/forms.json View File

@@ -1,4 +1,7 @@
{
"FirstName": "First name",
"LastName": "Last name",
"Message": "Message",
"FullName": "Full name",
"Username": "Username",
"Email": "Email",

+ 8
- 0
schemas/contactSchema.js View File

@@ -0,0 +1,8 @@
import * as Yup from 'yup';

export const contactSchema = Yup.object().shape({
firstName: Yup.string().required('First name is required'),
lastName: Yup.string().required('Last name is required'),
email: Yup.string().email('Enter valid email').required('Email is required'),
message: Yup.string().required('Message is required'),
});

Loading…
Cancel
Save