From a7bb9a2cae2bb14d3eaaa564327e88c3187c051c Mon Sep 17 00:00:00 2001 From: Strift Date: Thu, 30 Jan 2025 22:09:50 +0800 Subject: [PATCH] Update layout success and error layout --- src/components/NewsletterForm.jsx | 95 +++++++++++++++++-- src/components/RightPanel.jsx | 2 +- .../icons/heroicons/ArrowPathicon.jsx | 20 ++++ src/components/icons/heroicons/CheckIcon.jsx | 20 ++++ 4 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 src/components/icons/heroicons/ArrowPathicon.jsx create mode 100644 src/components/icons/heroicons/CheckIcon.jsx diff --git a/src/components/NewsletterForm.jsx b/src/components/NewsletterForm.jsx index be78b344..2fca83b1 100644 --- a/src/components/NewsletterForm.jsx +++ b/src/components/NewsletterForm.jsx @@ -1,7 +1,27 @@ import React from 'react' -import styled from 'styled-components' - +import styled, { keyframes } from 'styled-components' import useNewsletter from 'hooks/useNewsletter' +import ArrowPathIcon from './icons/heroicons/ArrowPathicon' +import CheckIcon from './icons/heroicons/CheckIcon' + +const spin = keyframes` + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +` + +const SpinningIcon = styled.div` + display: inline-flex; + animation: ${spin} 1s linear infinite; + + svg { + width: 1.25rem; + height: 1.25rem; + } +` const Input = styled.input` width: 100%; @@ -34,23 +54,74 @@ const Button = styled.button` font-weight: 600; cursor: pointer; transition: background-color 0.2s; + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; &:hover { background: ${(p) => p.theme.colors.main.dark}; } + + &:disabled { + opacity: 0.7; + cursor: not-allowed; + } +` + +const ErrorMessage = styled.p` + color: #dc2626; + font-size: 0.875rem; + margin-top: 0.5rem; +` + +const SuccessMessage = styled.div` + display: flex; + text-align: center; + align-items: center; + justify-content: center; + gap: 0.5rem; + background-color: #f0fdf4; + border: 1px solid #86efac; + border-radius: 8px; + padding: 0rem; + color: #166534; + + svg { + width: 1.25rem; + height: 1.25rem; + } + + p { + font-size: 0.875rem; + color: #15803d; + } ` const NewsletterForm = () => { const [email, setEmail] = React.useState('') const { subscribe } = useNewsletter() const [status, setStatus] = React.useState('idle') + const [error, setError] = React.useState(null) const handleSubmit = (e) => { e.preventDefault() setStatus('loading') subscribe(email) .then(() => setStatus('success')) - .catch(() => setStatus('error')) + .catch((err) => { + setStatus('error') + setError(err.message) + }) + } + + if (status === 'success') { + return ( + + +

Thanks for subscribing!

+
+ ) } return ( @@ -62,11 +133,21 @@ const NewsletterForm = () => { onChange={(e) => setEmail(e.target.value)} disabled={status === 'loading'} required + style={{ marginTop: '0rem' }} /> - - {status === 'loading' &&

Loading...

} - {status === 'success' &&

Success!

} - {status === 'error' &&

Error

} + + {status === 'error' && {error}} ) } diff --git a/src/components/RightPanel.jsx b/src/components/RightPanel.jsx index a43c168a..0fc84463 100644 --- a/src/components/RightPanel.jsx +++ b/src/components/RightPanel.jsx @@ -180,7 +180,7 @@ const RightPanel = ({ isOpen, onClose }) => ( Get monthly updates about new features and tips to get the the most out of Meilisearch. diff --git a/src/components/icons/heroicons/ArrowPathicon.jsx b/src/components/icons/heroicons/ArrowPathicon.jsx new file mode 100644 index 00000000..6e81b08f --- /dev/null +++ b/src/components/icons/heroicons/ArrowPathicon.jsx @@ -0,0 +1,20 @@ +import React from 'react' + +export default function ArrowPathIcon() { + return ( + + + + ) +} diff --git a/src/components/icons/heroicons/CheckIcon.jsx b/src/components/icons/heroicons/CheckIcon.jsx new file mode 100644 index 00000000..15c4c48a --- /dev/null +++ b/src/components/icons/heroicons/CheckIcon.jsx @@ -0,0 +1,20 @@ +import React from 'react' + +export default function CheckIcon() { + return ( + + + + ) +}