From 3f5f79aeb918995b384c1e56df977aad3ab3a6c0 Mon Sep 17 00:00:00 2001 From: Guilherme da Silva Benevides Date: Mon, 28 Oct 2024 17:24:49 -0300 Subject: [PATCH 1/7] feat: initial props and visual of newsletter --- .deco/blocks/Footer.json | 175 ++---------------- .deco/blocks/pages-home-c4bcbfb771e9.json | 20 -- components/footer/Newsletter.tsx | 113 +++++++++++ components/footer/NewsletterStars.tsx | 59 ++++++ components/footer/index.tsx | 13 ++ components/footer/types.ts | 65 +++++++ components/header/GeolocationOffers/index.tsx | 2 +- components/header/NavItem.tsx | 2 +- components/minicart/MinicartEmpty.tsx | 2 +- components/ui/Input.tsx | 15 ++ sdk/htmlSanitizer.ts | 40 ++++ sections/Footer/Footer.tsx | 128 +------------ static/tailwind.css | 159 ++++++++++++++-- tailwind.config.ts | 7 + tailwind.css | 7 + 15 files changed, 481 insertions(+), 326 deletions(-) create mode 100644 components/footer/Newsletter.tsx create mode 100644 components/footer/NewsletterStars.tsx create mode 100644 components/footer/index.tsx create mode 100644 components/footer/types.ts create mode 100644 sdk/htmlSanitizer.ts diff --git a/.deco/blocks/Footer.json b/.deco/blocks/Footer.json index 6e76413..37d9393 100644 --- a/.deco/blocks/Footer.json +++ b/.deco/blocks/Footer.json @@ -1,167 +1,14 @@ { "__resolveType": "site/sections/Footer/Footer.tsx", - "links": [ - { - "title": "Our Company", - "children": [ - { - "title": "About us", - "href": "#" - }, - { - "title": "Our blog", - "href": "#" - }, - { - "title": "Stores", - "href": "#" - }, - { - "title": "Work with us", - "href": "#" - } - ], - "href": "#" - }, - { - "title": "Orders & Purchases", - "href": "#", - "children": [ - { - "title": "Check order status", - "href": "#" - }, - { - "title": "Return and exchanges", - "href": "#" - }, - { - "title": "Product retail", - "href": "#" - }, - { - "title": "Gift cards", - "href": "#" - } - ] - }, - { - "title": "Support & Services", - "href": "#", - "children": [ - { - "title": "Support Center", - "href": "#" - }, - { - "title": "Schedule a service", - "href": "#" - }, - { - "title": "Contact us", - "href": "#" - } - ] - }, - { - "title": "Support & Services", - "children": [ - { - "title": "Support Center", - "href": "#" - }, - { - "title": "Schedule a service", - "href": "#" - }, - { - "title": "Contact us", - "href": "#" - } - ], - "href": "#" - } - ], - "social": [ - { - "alt": "facebook", - "href": "#", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/66137259-6bdb-4322-bed1-a2593560934c" - }, - { - "alt": "Instagram", - "href": "#", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/e71ae7f3-0f51-4185-af0a-fca08ebe4451" - }, - { - "alt": "Pinterest", - "href": "#", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/4becba39-fc08-4df2-bb5d-5e843f375deb" - }, - { - "alt": "X", - "href": "#", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/179a9ee9-3813-47b8-96eb-11e0c5558ede" - } - ], - "paymentMethods": [ - { - "alt": "Paypal", - "href": "#", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/7d858621-469e-4528-91b5-8c79fc413162" - }, - { - "alt": "Mastercard", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/88ab870c-4256-44b4-8da3-3cefe0436e87" - }, - { - "alt": "Maestro", - "href": "#", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/e94aaf80-25f5-4e23-8708-14d78ffdebbb" - }, - { - "alt": "Google Pay", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/ccddc66e-baa8-4b44-a52c-ea48d8e111b5" - }, - { - "alt": "Elo", - "href": "#", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/11f90dd4-91b5-4b60-9304-f8a7a9be84eb" - }, - { - "alt": "Diners", - "href": "#", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/20bb8e66-5495-4f92-a6d0-4967a66f3a44" - }, - { - "alt": "Apple Pay", - "href": "#", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/d4227ed7-333d-49b8-b3e2-35719f606640" - }, - { - "alt": "Amex", - "href": "#", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/023472cf-782d-4a22-82d9-ecdf18466d96" - }, - { - "alt": "Visa", - "image": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/2d213fd6-2754-4e92-a6f1-03825f71c7af" - } - ], - "policies": [ - { - "title": "Privacy Policy", - "href": "#" - }, - { - "title": "Terms and Conditions", - "href": "#" - }, - { - "title": "Cookies Policy", - "href": "#" - } - ], - "logo": "https://ozksgdmyrqcxcwhnbepg.supabase.co/storage/v1/object/public/assets/2177/f1faab73-e4ff-4037-b7c4-5d02bd0b1209", - "trademark": "TM & © 2023 Deco Storefront, Inc." + "newsletter": { + "title": "

Fique por dentro das novidades da Alphabeto!

", + "description": "Saiba mais sobre os lançamentos, as estampas mais divertidas e detalhes que encantam!" + }, + "columns": [], + "card": { + "button": {}, + "image": {} + }, + "tecnologiesLogo": {}, + "cardFlags": [] } \ No newline at end of file diff --git a/.deco/blocks/pages-home-c4bcbfb771e9.json b/.deco/blocks/pages-home-c4bcbfb771e9.json index 1eb3984..e327c95 100644 --- a/.deco/blocks/pages-home-c4bcbfb771e9.json +++ b/.deco/blocks/pages-home-c4bcbfb771e9.json @@ -111,26 +111,6 @@ } } }, - { - "__resolveType": "website/sections/Rendering/Lazy.tsx", - "section": { - "__resolveType": "site/sections/Newsletter/Newsletter.tsx", - "label": "Sign up", - "placeholder": "Email address", - "empty": { - "title": "Get top deals, latest trends, and more.", - "description": "Receive our news and promotions in advance. Enjoy and get 10% off your first purchase. For more information click here." - }, - "success": { - "title": "Thank you for subscribing!", - "description": "You’re now signed up to receive the latest news, trends, and exclusive promotions directly to your inbox. Stay tuned!" - }, - "failed": { - "title": "Oops!. Something went wrong!", - "description": "Something went wrong. Please try again. If the problem persists, please contact us." - } - } - }, { "__resolveType": "website/sections/Rendering/Lazy.tsx", "section": { diff --git a/components/footer/Newsletter.tsx b/components/footer/Newsletter.tsx new file mode 100644 index 0000000..3661328 --- /dev/null +++ b/components/footer/Newsletter.tsx @@ -0,0 +1,113 @@ +import { + NewsletterStarsOne, + NewsletterStarsThree, + NewsletterStarsTwo, +} from "site/components/footer/NewsletterStars.tsx"; +import { Newsletter as Props } from "site/components/footer/types.ts"; +import Button from "site/components/ui/Button.tsx"; +import Input, { RadioInput } from "site/components/ui/Input.tsx"; +import { sanitizeHTMLCode } from "site/sdk/htmlSanitizer.ts"; + +export default function Newsletter(props: Props) { + const sanitizedCode = sanitizeHTMLCode(props.title, { + removeAttributes: true, + removeWrapperTag: true, + allowedTags: ["span", "strong"], + }); + return ( +
+
+
+

+ {props.description && ( +

+ {props.description} +

+ )} +

+
+ + + +
+
+ + Tenho Interresse em: + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+ + + +
+
+ ); +} diff --git a/components/footer/NewsletterStars.tsx b/components/footer/NewsletterStars.tsx new file mode 100644 index 0000000..7c6bd23 --- /dev/null +++ b/components/footer/NewsletterStars.tsx @@ -0,0 +1,59 @@ +interface NewsletterStarsProps { + className?: string; +} + +export const NewsletterStarsOne = ({ className }: NewsletterStarsProps) => ( + + + + +); + +export const NewsletterStarsTwo = ({ className }: NewsletterStarsProps) => ( + + + +); + +export const NewsletterStarsThree = ({ className }: NewsletterStarsProps) => ( + + + + +); diff --git a/components/footer/index.tsx b/components/footer/index.tsx new file mode 100644 index 0000000..fa250e0 --- /dev/null +++ b/components/footer/index.tsx @@ -0,0 +1,13 @@ +import Newsletter from "site/components/footer/Newsletter.tsx"; +import { Props } from "site/components/footer/types.ts"; +import Section from "site/components/ui/Section.tsx"; + +export default function Footer(props: Props) { + return ( +
+ +
+ ); +} + +export const LoadingFallback = () => ; diff --git a/components/footer/types.ts b/components/footer/types.ts new file mode 100644 index 0000000..1de70d4 --- /dev/null +++ b/components/footer/types.ts @@ -0,0 +1,65 @@ +import { ImageWidget, RichText } from "apps/admin/widgets.ts"; + +/** @title {{title}} */ +export interface Item { + title: string; + /** @title URL */ + href: string; +} + +/** @title {{title}} */ +export interface Menu { + title: string; + /** @title URL */ + href: string; + itens: Item[]; +} + +/** @title {{title}} */ +export interface SocialLogo { + title: string; + logo: ImageWidget; +} + +export interface Column { + menus: Menu[]; + socialLogos?: SocialLogo[]; +} + +export interface Newsletter { + title: RichText; + description?: string; +} + +export interface Card { + title: string; + badge?: string; + description: string; + button: { + text: string; + href: string; + }; + image: { + desktop: ImageWidget; + mobile: ImageWidget; + }; +} + +export interface TecnologiesLogo { + econverse: ImageWidget; + vtex: ImageWidget; +} +/** @title {{title}} */ +export interface CardFlag { + title: string; + image: ImageWidget; +} + +export interface Props { + newsletter: Newsletter; + columns: Column[]; + card: Card; + tecnologiesLogo: TecnologiesLogo; + copyright: string; + cardFlags: CardFlag[]; +} diff --git a/components/header/GeolocationOffers/index.tsx b/components/header/GeolocationOffers/index.tsx index 1fc39be..9292c06 100644 --- a/components/header/GeolocationOffers/index.tsx +++ b/components/header/GeolocationOffers/index.tsx @@ -213,7 +213,7 @@ export default function GeolocationOffers(props: Props) { > -

+

Quer ofertas?

diff --git a/components/header/NavItem.tsx b/components/header/NavItem.tsx index 7a8e52d..644e3f9 100644 --- a/components/header/NavItem.tsx +++ b/components/header/NavItem.tsx @@ -79,7 +79,7 @@ function NavItem({ href, menuItem, image, submenu }: Items) { >

-
+
{menuItem}
    diff --git a/components/minicart/MinicartEmpty.tsx b/components/minicart/MinicartEmpty.tsx index 728827d..a342ae2 100644 --- a/components/minicart/MinicartEmpty.tsx +++ b/components/minicart/MinicartEmpty.tsx @@ -23,7 +23,7 @@ export function MinicartEmpty({ content }: Props) {
    {content?.icon && Sacola} -

    +

    {content?.title}

    diff --git a/components/ui/Input.tsx b/components/ui/Input.tsx index 91536de..e0090a3 100644 --- a/components/ui/Input.tsx +++ b/components/ui/Input.tsx @@ -18,3 +18,18 @@ export default function Input(props: InputProps) { ); } + +export function RadioInput(props: InputProps) { + const { className, ...rest } = props; + return ( + + + ); +} diff --git a/sdk/htmlSanitizer.ts b/sdk/htmlSanitizer.ts new file mode 100644 index 0000000..096898d --- /dev/null +++ b/sdk/htmlSanitizer.ts @@ -0,0 +1,40 @@ +const removeAttributes = (html: string) => { + return html.replace(/<[^>]*>/g, (tag) => { + return tag.replace(/ [^=]+="[^"]*"/g, ""); + }); +}; +const keepAllowedTags = (html: string, tags: string[]) => { + const closeTags = tags.map((tag) => `/${tag}`); + return html.replace(/<[^>]*>/g, (tag) => { + const tagName = tag.match(/<([^>\s]+)/)?.[1]; + if (!tagName) return ""; + return tags.includes(tagName) || closeTags.includes(tagName) ? tag : ""; + }); +}; +const removeWrapperTag = (html: string) => { + return html.replace(/<[^>]*>(.*)<\/[^>]*>/, "$1"); +}; + +interface SanitizeOptions { + removeWrapperTag?: boolean; + removeAttributes?: boolean; + allowedTags?: string[]; +} + +export const sanitizeHTMLCode = (html: string, opitions: SanitizeOptions) => { + let result = html; + + if (opitions.removeWrapperTag) { + result = removeWrapperTag(result); + console.log(result); + } + if (opitions.removeAttributes) { + result = removeAttributes(result); + console.log(result); + } + if (opitions.allowedTags) { + result = keepAllowedTags(result, opitions.allowedTags); + console.log(result); + } + return result; +}; diff --git a/sections/Footer/Footer.tsx b/sections/Footer/Footer.tsx index 2af0626..28d0bfb 100644 --- a/sections/Footer/Footer.tsx +++ b/sections/Footer/Footer.tsx @@ -1,127 +1 @@ -import { type ImageWidget } from "apps/admin/widgets.ts"; -import Image from "apps/website/components/Image.tsx"; -import PoweredByDeco from "apps/website/components/PoweredByDeco.tsx"; -import Section from "../../components/ui/Section.tsx"; - -/** @titleBy title */ -interface Item { - title: string; - href: string; -} - -/** @titleBy title */ -interface Link extends Item { - children: Item[]; -} - -/** @titleBy alt */ -interface Social { - alt?: string; - href?: string; - image: ImageWidget; -} - -interface Props { - links?: Link[]; - social?: Social[]; - paymentMethods?: Social[]; - policies?: Item[]; - logo?: ImageWidget; - trademark?: string; -} - -function Footer({ - links = [], - social = [], - policies = [], - paymentMethods = [], - logo, - trademark, -}: Props) { - return ( -
    -
    -
      - {links.map(({ title, href, children }) => ( -
    • - {title} -
        - {children.map(({ title, href }) => ( -
      • - - {title} - -
      • - ))} -
      -
    • - ))} -
    - -
    -
      - {social.map(({ image, href, alt }) => ( -
    • - - {alt} - -
    • - ))} -
    -
      - {paymentMethods.map(({ image, alt }) => ( -
    • - {alt} -
    • - ))} -
    -
    - -
    - -
    -
      - {policies.map(({ title, href }) => ( -
    • - - {title} - -
    • - ))} -
    - -
    -
    - -
    - {trademark} -
    - -
    - Powered by - -
    -
    -
    -
    - ); -} - -export const LoadingFallback = () => ; - -export default Footer; +export { default, LoadingFallback } from "site/components/footer/index.tsx"; diff --git a/static/tailwind.css b/static/tailwind.css index 9313406..6f0d0fd 100644 --- a/static/tailwind.css +++ b/static/tailwind.css @@ -715,6 +715,11 @@ html { color: var(--fallback-nc,oklch(var(--nc)/var(--tw-text-opacity))) !important; } + .radio-primary:hover { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); + } + .tab:hover { --tw-text-opacity: 1; } @@ -2854,6 +2859,23 @@ details.collapse summary::-webkit-details-marker { box-shadow: 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset, 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset; } +.radio-primary { + --chkbg: var(--p); + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); +} +.radio-primary:focus-visible { + outline-color: var(--fallback-p,oklch(var(--p)/1)); +} +.radio-primary:checked, + .radio-primary[aria-checked="true"] { + --tw-border-opacity: 1; + border-color: var(--fallback-p,oklch(var(--p)/var(--tw-border-opacity))); + --tw-bg-opacity: 1; + background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); + --tw-text-opacity: 1; + color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity))); +} .radio:disabled { cursor: not-allowed; opacity: 0.2; @@ -3484,6 +3506,10 @@ details.collapse summary::-webkit-details-marker { border-end-end-radius: inherit; border-start-end-radius: inherit; } +[type="radio"].radio-xs { + height: 1rem; + width: 1rem; +} .tabs-md :where(.tab) { height: 2rem; font-size: 0.875rem; @@ -3641,6 +3667,9 @@ details.collapse summary::-webkit-details-marker { .bottom-\[24px\] { bottom: 24px; } +.bottom-\[45px\] { + bottom: 45px; +} .left-0 { left: 0px; } @@ -3653,6 +3682,9 @@ details.collapse summary::-webkit-details-marker { .left-4 { left: 1rem; } +.left-\[429px\] { + left: 429px; +} .left-\[50\%\] { left: 50%; } @@ -3671,9 +3703,15 @@ details.collapse summary::-webkit-details-marker { .right-6 { right: 1.5rem; } +.right-\[10px\] { + right: 10px; +} .right-\[14px\] { right: 14px; } +.right-\[85px\] { + right: 85px; +} .top-0 { top: 0px; } @@ -3698,6 +3736,12 @@ details.collapse summary::-webkit-details-marker { .top-\[41px\] { top: 41px; } +.top-\[51px\] { + top: 51px; +} +.top-\[57px\] { + top: 57px; +} .top-\[70px\] { top: 70px; } @@ -3938,9 +3982,6 @@ details.collapse summary::-webkit-details-marker { .h-6 { height: 1.5rem; } -.h-8 { - height: 2rem; -} .h-\[102px\] { height: 102px; } @@ -4203,6 +4244,9 @@ details.collapse summary::-webkit-details-marker { .max-w-\[139px\] { max-width: 139px; } +.max-w-\[1440px\] { + max-width: 1440px; +} .max-w-\[2px\] { max-width: 2px; } @@ -4221,6 +4265,9 @@ details.collapse summary::-webkit-details-marker { .max-w-\[360px\] { max-width: 360px; } +.max-w-\[371px\] { + max-width: 371px; +} .max-w-\[380px\] { max-width: 380px; } @@ -4363,6 +4410,9 @@ details.collapse summary::-webkit-details-marker { .grid-rows-1 { grid-template-rows: repeat(1, minmax(0, 1fr)); } +.grid-rows-2 { + grid-template-rows: repeat(2, minmax(0, 1fr)); +} .grid-rows-\[1fr_32px_1fr_64px\] { grid-template-rows: 1fr 32px 1fr 64px; } @@ -4378,9 +4428,6 @@ details.collapse summary::-webkit-details-marker { .flex-wrap { flex-wrap: wrap; } -.flex-nowrap { - flex-wrap: nowrap; -} .place-items-center { place-items: center; } @@ -4438,6 +4485,9 @@ details.collapse summary::-webkit-details-marker { .gap-\[10px\] { gap: 10px; } +.gap-\[14px\] { + gap: 14px; +} .gap-\[16px\] { gap: 16px; } @@ -4447,6 +4497,9 @@ details.collapse summary::-webkit-details-marker { .gap-\[2px\] { gap: 2px; } +.gap-\[30px\] { + gap: 30px; +} .gap-\[3px\] { gap: 3px; } @@ -4644,10 +4697,6 @@ details.collapse summary::-webkit-details-marker { --tw-border-opacity: 1; border-color: rgb(255 133 154 / var(--tw-border-opacity)); } -.border-base-100 { - --tw-border-opacity: 1; - border-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-border-opacity))); -} .border-base-200 { --tw-border-opacity: 1; border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity))); @@ -4987,6 +5036,9 @@ details.collapse summary::-webkit-details-marker { .pt-\[130px\] { padding-top: 130px; } +.pt-\[14px\] { + padding-top: 14px; +} .pt-\[23px\] { padding-top: 23px; } @@ -5011,8 +5063,8 @@ details.collapse summary::-webkit-details-marker { .font-\[\#676767\] { font-family: #676767; } -.font-\[\'BeccaPerry\'\] { - font-family: 'BeccaPerry'; +.font-beccaPerry { + font-family: BeccaPerry, sans-serif; } .\!text-sm { font-size: 0.875rem !important; @@ -5066,6 +5118,9 @@ details.collapse summary::-webkit-details-marker { .text-\[25px\] { font-size: 25px; } +.text-\[28px\] { + font-size: 28px; +} .text-\[2rem\] { font-size: 2rem; } @@ -5141,6 +5196,9 @@ details.collapse summary::-webkit-details-marker { .leading-5 { line-height: 1.25rem; } +.leading-8 { + line-height: 2rem; +} .leading-\[1\.125rem\] { line-height: 1.125rem; } @@ -5468,6 +5526,13 @@ details.collapse summary::-webkit-details-marker { .customizeScroll::-webkit-scrollbar-thumb:hover { background: #d6de23; } + +.radio:not(:checked) { + background-color: white; +} +.radio:checked { + box-shadow: 0 0 0 4px white inset, 0 0 0 4px white inset; +} .invalid\:input-error:invalid { --tw-border-opacity: 1; border-color: var(--fallback-er,oklch(var(--er)/var(--tw-border-opacity))); @@ -5788,6 +5853,10 @@ details.collapse summary::-webkit-details-marker { margin-right: auto; } + .desk\:mr-\[99px\] { + margin-right: 99px; + } + .desk\:block { display: block; } @@ -5796,6 +5865,10 @@ details.collapse summary::-webkit-details-marker { display: grid; } + .desk\:hidden { + display: none; + } + .desk\:h-\[295px\] { height: 295px; } @@ -5804,6 +5877,10 @@ details.collapse summary::-webkit-details-marker { width: 443px; } + .desk\:w-auto { + width: auto; + } + .desk\:w-full { width: 100%; } @@ -5812,6 +5889,10 @@ details.collapse summary::-webkit-details-marker { max-width: 375px; } + .desk\:max-w-\[422px\] { + max-width: 422px; + } + .desk\:max-w-\[95rem\] { max-width: 95rem; } @@ -5820,6 +5901,10 @@ details.collapse summary::-webkit-details-marker { grid-template-columns: 185px 1fr 443px; } + .desk\:flex-row { + flex-direction: row; + } + .desk\:gap-11 { gap: 2.75rem; } @@ -5836,6 +5921,10 @@ details.collapse summary::-webkit-details-marker { border-right-width: 1px; } + .desk\:p-10 { + padding: 2.5rem; + } + .desk\:px-10 { padding-left: 2.5rem; padding-right: 2.5rem; @@ -5856,6 +5945,27 @@ details.collapse summary::-webkit-details-marker { .desk\:pt-0 { padding-top: 0px; } + + .desk\:text-left { + text-align: left; + } + + .desk\:text-\[40px\] { + font-size: 40px; + } + + .desk\:text-base { + font-size: 1rem; + line-height: 1.5rem; + } + + .desk\:font-medium { + font-weight: 500; + } + + .desk\:leading-\[48px\] { + line-height: 48px; + } } @media (max-width: 1200px) { @@ -5872,6 +5982,24 @@ details.collapse summary::-webkit-details-marker { font-size: 12px; } } +@media (max-width: 1330px) { + + .max-1330\:bottom-6 { + bottom: 1.5rem; + } + + .max-1330\:mr-0 { + margin-right: 0px; + } + + .max-1330\:max-w-\[300px\] { + max-width: 300px; + } + + .max-1330\:grid-cols-\[250px_1fr\] { + grid-template-columns: 250px 1fr; + } +} .\[\&\[disabled\]\]\:border-\[\#C5C5C5\][disabled] { --tw-border-opacity: 1; border-color: rgb(197 197 197 / var(--tw-border-opacity)); @@ -5887,6 +6015,13 @@ details.collapse summary::-webkit-details-marker { .\[\&_section\]\:contents section { display: contents; } +.\[\&_strong\]\:font-medium strong { + font-weight: 500; +} +.\[\&_strong\]\:text-primary strong { + --tw-text-opacity: 1; + color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity))); +} .htmx-request .\[\.htmx-request_\&\]\:block { display: block; } diff --git a/tailwind.config.ts b/tailwind.config.ts index db81ba0..6cd6b54 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -28,6 +28,9 @@ export default { "100%": { transform: "translateX(-50%)" }, }, }, + fontFamily: { + "beccaPerry": ["BeccaPerry", "sans-serif"], + }, }, screens: { @@ -42,6 +45,10 @@ export default { "desk-small": { max: "1200px" }, // =< @media (min-width: 1200px) { ... } + + "max-1330": { + max: "1330px", + }, }, }, }; diff --git a/tailwind.css b/tailwind.css index 77665f0..f51610e 100644 --- a/tailwind.css +++ b/tailwind.css @@ -75,3 +75,10 @@ .customizeScroll::-webkit-scrollbar-thumb:hover { background: #d6de23; } + +.radio:not(:checked) { + background-color: white; +} +.radio:checked { + box-shadow: 0 0 0 4px white inset, 0 0 0 4px white inset; +} From 7e5183c711e2773138d7bda6b88933ebbb01fbbb Mon Sep 17 00:00:00 2001 From: Guilherme da Silva Benevides Date: Wed, 30 Oct 2024 17:22:10 -0300 Subject: [PATCH 2/7] feat: finished newsletter --- components/footer/Newsletter.tsx | 119 +++++++++++++++++++++++++++++-- components/footer/index.tsx | 1 - components/footer/types.ts | 2 + components/ui/Input.tsx | 2 +- sdk/htmlSanitizer.ts | 3 - static/tailwind.css | 21 ++++-- tailwind.config.ts | 3 + 7 files changed, 136 insertions(+), 15 deletions(-) diff --git a/components/footer/Newsletter.tsx b/components/footer/Newsletter.tsx index 3661328..3e739b0 100644 --- a/components/footer/Newsletter.tsx +++ b/components/footer/Newsletter.tsx @@ -1,3 +1,5 @@ +import { useScript } from "@deco/deco/hooks"; +import { AppContext } from "site/apps/deco/vtex.ts"; import { NewsletterStarsOne, NewsletterStarsThree, @@ -7,17 +9,92 @@ import { Newsletter as Props } from "site/components/footer/types.ts"; import Button from "site/components/ui/Button.tsx"; import Input, { RadioInput } from "site/components/ui/Input.tsx"; import { sanitizeHTMLCode } from "site/sdk/htmlSanitizer.ts"; +import { useComponent } from "site/sections/Component.tsx"; + +const submitButtonWrapperId = "NEWSLETTER_FOOTER_SUBMIT_BUTTON_WRAPPER"; +const formId = "NEWSLETTER_FOOTER_FORM"; + +const beforeFormSubmit = (formId: string) => { + const form = document.getElementById(formId) as HTMLFormElement; + const submitButton = form.querySelector( + "button[type=submit]", + ) as HTMLButtonElement; + submitButton.disabled = true; + const inputs = form.querySelectorAll("input"); + inputs.forEach((input) => { + input.disabled = true; + }); +}; + +const afterFormSubmit = async (formId: string) => { + await new Promise((resolve) => setTimeout(resolve, 2000)); + const form = document.getElementById(formId) as HTMLFormElement; + form.reset(); + const submitButton = form.querySelector( + "button[type=submit]", + ) as HTMLButtonElement; + submitButton.disabled = false; + submitButton.innerText = "Enviar"; + const inputs = form.querySelectorAll("input"); + inputs.forEach((input) => { + input.disabled = false; + }); +}; + +export async function loader(props: Props, req: Request, ctx: AppContext) { + if (req.method === "POST") { + try { + const formData = await req.formData(); + const name = formData.get("name") as string; + const email = formData.get("email") as string; + const child_name = formData.get("childrenName") as string; + + const interestMap = { + "any": "Ambos", + "girls": "Menina", + "boys": "Menino", + }; + const interest = formData.get("interest") as keyof typeof interestMap; + + await ctx.invoke("vtex/actions/masterdata/createDocument.ts", { + data: { + name, + accept: true, + email, + gender: interestMap[interest], + child_name, + }, + acronym: "NW", + }); + + return { + ...props, + formState: "success", + }; + } catch (_e) { + return { + ...props, + formState: "error", + }; + } + } + return { + ...props, + }; +} export default function Newsletter(props: Props) { + const formState = props.formState ?? "idle"; const sanitizedCode = sanitizeHTMLCode(props.title, { removeAttributes: true, removeWrapperTag: true, allowedTags: ["span", "strong"], }); + return (
    -
    +

    )}

    -
    +
    - +
    + {formState === "idle" + ? ( + + ) + : ( + + )} +
    - +
    diff --git a/components/footer/index.tsx b/components/footer/index.tsx index fa250e0..5270cc6 100644 --- a/components/footer/index.tsx +++ b/components/footer/index.tsx @@ -1,7 +1,6 @@ import Newsletter from "site/components/footer/Newsletter.tsx"; import { Props } from "site/components/footer/types.ts"; import Section from "site/components/ui/Section.tsx"; - export default function Footer(props: Props) { return (
    diff --git a/components/footer/types.ts b/components/footer/types.ts index 1de70d4..5f32f9c 100644 --- a/components/footer/types.ts +++ b/components/footer/types.ts @@ -29,6 +29,8 @@ export interface Column { export interface Newsletter { title: RichText; description?: string; + /** @hide true */ + formState?: "idle" | "success" | "error"; } export interface Card { diff --git a/components/ui/Input.tsx b/components/ui/Input.tsx index e0090a3..1b0b88e 100644 --- a/components/ui/Input.tsx +++ b/components/ui/Input.tsx @@ -11,7 +11,7 @@ export default function Input(props: InputProps) { diff --git a/sdk/htmlSanitizer.ts b/sdk/htmlSanitizer.ts index 096898d..bebfa19 100644 --- a/sdk/htmlSanitizer.ts +++ b/sdk/htmlSanitizer.ts @@ -26,15 +26,12 @@ export const sanitizeHTMLCode = (html: string, opitions: SanitizeOptions) => { if (opitions.removeWrapperTag) { result = removeWrapperTag(result); - console.log(result); } if (opitions.removeAttributes) { result = removeAttributes(result); - console.log(result); } if (opitions.allowedTags) { result = keepAllowedTags(result, opitions.allowedTags); - console.log(result); } return result; }; diff --git a/static/tailwind.css b/static/tailwind.css index 6f0d0fd..74f5bd7 100644 --- a/static/tailwind.css +++ b/static/tailwind.css @@ -5766,6 +5766,10 @@ details.collapse summary::-webkit-details-marker { --tw-border-opacity: 1; border-color: rgb(197 197 197 / var(--tw-border-opacity)); } +.disabled\:border-\[\#D8D7D5\]:disabled { + --tw-border-opacity: 1; + border-color: rgb(216 215 213 / var(--tw-border-opacity)); +} .disabled\:\!bg-transparent:disabled { background-color: transparent !important; } @@ -5781,6 +5785,9 @@ details.collapse summary::-webkit-details-marker { --tw-bg-opacity: 1; background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity))); } +.disabled\:bg-transparent:disabled { + background-color: transparent; +} .disabled\:\!text-error:disabled { --tw-text-opacity: 1 !important; color: var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity))) !important; @@ -5793,6 +5800,10 @@ details.collapse summary::-webkit-details-marker { --tw-text-opacity: 1; color: rgb(103 103 103 / var(--tw-text-opacity)); } +.disabled\:text-\[\#D8D7D5\]:disabled { + --tw-text-opacity: 1; + color: rgb(216 215 213 / var(--tw-text-opacity)); +} .disabled\:\!opacity-50:disabled { opacity: 0.5 !important; } @@ -5991,13 +6002,15 @@ details.collapse summary::-webkit-details-marker { .max-1330\:mr-0 { margin-right: 0px; } +} +@media (max-width: 1240px) { - .max-1330\:max-w-\[300px\] { - max-width: 300px; + .max-1240\:left-\[310px\] { + left: 310px; } - .max-1330\:grid-cols-\[250px_1fr\] { - grid-template-columns: 250px 1fr; + .max-1240\:max-w-\[300px\] { + max-width: 300px; } } .\[\&\[disabled\]\]\:border-\[\#C5C5C5\][disabled] { diff --git a/tailwind.config.ts b/tailwind.config.ts index 6cd6b54..2214166 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -49,6 +49,9 @@ export default { "max-1330": { max: "1330px", }, + "max-1240": { + max: "1240px", + }, }, }, }; From f69124fadc86f23d9aeb86cab1b7ceb70331c25d Mon Sep 17 00:00:00 2001 From: Guilherme da Silva Benevides Date: Wed, 30 Oct 2024 17:37:09 -0300 Subject: [PATCH 3/7] fix: some issues in newsletter --- components/footer/Newsletter.tsx | 49 +++++++++++++++----------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/components/footer/Newsletter.tsx b/components/footer/Newsletter.tsx index 3e739b0..6c476de 100644 --- a/components/footer/Newsletter.tsx +++ b/components/footer/Newsletter.tsx @@ -27,14 +27,15 @@ const beforeFormSubmit = (formId: string) => { }; const afterFormSubmit = async (formId: string) => { - await new Promise((resolve) => setTimeout(resolve, 2000)); + await new Promise((resolve) => setTimeout(resolve, 3000)); const form = document.getElementById(formId) as HTMLFormElement; form.reset(); const submitButton = form.querySelector( "button[type=submit]", ) as HTMLButtonElement; submitButton.disabled = false; - submitButton.innerText = "Enviar"; + const span = submitButton.querySelector(".textSpan") as HTMLSpanElement; + span.innerHTML = "Enviar"; const inputs = form.querySelectorAll("input"); inputs.forEach((input) => { input.disabled = false; @@ -91,6 +92,12 @@ export default function Newsletter(props: Props) { allowedTags: ["span", "strong"], }); + const texts: Record = { + idle: "Enviar", + success: "Enviado", + error: "Erro", + }; + return (
    @@ -111,10 +118,10 @@ export default function Newsletter(props: Props) { className="flex flex-col desk:grid grid-cols-2 grid-rows-2 gap-4 desk:mr-[99px] max-1330:mr-0 w-full desk:w-auto" id={formId} hx-post={useComponent(import.meta.url, props)} - hx-target={`#${submitButtonWrapperId}`} - hx-swap="outerHTML" + hx-target={`#${submitButtonWrapperId} .textSpan`} + hx-swap="innerHTML" hx-indicator={`#${submitButtonWrapperId}`} - hx-select={`#${submitButtonWrapperId}`} + hx-select={`#${submitButtonWrapperId} .textSpan`} {...{ "hx-on::before-send": useScript(beforeFormSubmit, formId), "hx-on::after-settle": useScript(afterFormSubmit, formId), @@ -188,27 +195,17 @@ export default function Newsletter(props: Props) {
    -
    - {formState === "idle" - ? ( - - ) - : ( - - )} -
    + +
From ac787d91e0ea2c43f94f9c67adb32754fd18b3e5 Mon Sep 17 00:00:00 2001 From: Guilherme da Silva Benevides Date: Thu, 31 Oct 2024 16:13:27 -0300 Subject: [PATCH 4/7] feat: seccond row of footer --- .deco/blocks/Footer.json | 425 +++++++++++++++++++++- .vim/coc-settings.json | 10 + components/footer/Card.tsx | 52 +++ components/footer/MenusAndCardDesktop.tsx | 88 +++++ components/footer/MenusAndCardMobile.tsx | 134 +++++++ components/footer/Newsletter.tsx | 2 +- components/footer/index.tsx | 19 + components/footer/types.ts | 40 +- components/header/HeaderDesktop.tsx | 2 +- components/ui/Button.tsx | 134 +++---- components/ui/Icon.tsx | 4 +- static/sprites.svg | 8 +- static/tailwind.css | 108 +++++- tailwind.css | 6 +- 14 files changed, 940 insertions(+), 92 deletions(-) create mode 100644 .vim/coc-settings.json create mode 100644 components/footer/Card.tsx create mode 100644 components/footer/MenusAndCardDesktop.tsx create mode 100644 components/footer/MenusAndCardMobile.tsx diff --git a/.deco/blocks/Footer.json b/.deco/blocks/Footer.json index 37d9393..7d342e8 100644 --- a/.deco/blocks/Footer.json +++ b/.deco/blocks/Footer.json @@ -2,13 +2,426 @@ "__resolveType": "site/sections/Footer/Footer.tsx", "newsletter": { "title": "

Fique por dentro das novidades da Alphabeto!

", - "description": "Saiba mais sobre os lançamentos, as estampas mais divertidas e detalhes que encantam!" + "description": "Saiba mais sobre os lançamentos, as estampas mais divertidas e detalhes que encantam!", + "formState": "idle" }, - "columns": [], + "columns": [ + { + "menus": [ + { + "itens": [ + { + "href": "/marca", + "title": "Mundo Alphabeto" + }, + { + "title": "Encontre nossas lojas", + "href": "/lojas" + }, + { + "title": "Faça Parte", + "href": "/faca-parte" + } + ], + "title": "Intitucional" + } + ], + "socialLogos": [] + }, + { + "menus": [ + { + "itens": [ + { + "title": "Acompanhe seu pedido", + "href": "/account#/orders" + }, + { + "title": "Minha conta", + "href": "/account" + } + ], + "title": "Pedidos" + }, + { + "itens": [ + { + "title": "Faça a sua boneca", + "href": "/mini-me" + } + ], + "title": "Presentes" + } + ], + "socialLogos": [] + }, + { + "menus": [ + { + "itens": [ + { + "title": "Resgate seu cashback", + "href": "/regulamento-cashback" + }, + { + "title": "Termos de uso cashback", + "href": "/termos-e-condicoes" + }, + { + "title": "Termos e condições", + "href": "/termos-e-condicoes" + }, + { + "title": "Privacidade e segurança", + "href": "/privacidade" + }, + { + "title": "Formas de entrega", + "href": "/formas-entrega" + }, + { + "title": "Trocas e devoluções", + "href": "/trocas-devolucao" + }, + { + "title": "Procon", + "href": "http://www.procon.rj.gov.br/", + "openInNewTab": true + } + ], + "title": "Ajuda" + } + ], + "socialLogos": [] + }, + { + "menus": [ + { + "itens": [ + { + "title": "Fale com as fadinhas", + "href": "/central-atendimento" + }, + { + "title": "Perguntas frequentes ", + "href": "/duvidas-frequentes" + }, + { + "title": "E-mail: sac@alphabeto.com", + "href": "malito:sac@alphabeto.com", + "openInNewTab": false + }, + { + "title": "Whatsapp: (21) 99942-2795", + "href": "https://api.whatsapp.com/send/?phone=5521999422795&text&type=phone_number&app_absent=0", + "openInNewTab": true + }, + { + "title": "Contato: privacidade@alphabeto.com", + "href": "malito:privacidade@alphabeto.com" + } + ], + "title": "Fale conosco" + } + ], + "socialLogos": [ + { + "title": "Instagram", + "logo": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/c5470252-25f8-4e79-ac45-525ce9692923/instagram.svg", + "url": "https://www.instagram.com/lojaalphabeto/" + }, + { + "title": "Facebook", + "logo": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/9ff8b37a-125e-41ed-9f0b-5a954d7eef6e/facebook.svg", + "url": "https://www.facebook.com/lojaalphabeto" + }, + { + "title": "YouTube", + "logo": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/3f32ee3c-6b0d-4c35-b527-27724e32ec40/youtube.svg", + "url": "https://www.youtube.com/user/alphabetooficial" + }, + { + "url": "https://www.linkedin.com/company/lojaalphabeto", + "logo": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/a9468de9-05d9-4919-a8d1-814a9bb95500/linkedin.svg", + "title": "Linkedin" + }, + { + "title": "Spotify", + "logo": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/68d3dcab-b457-4892-8efe-9bad60286d3c/spotify.svg", + "url": "https://open.spotify.com/user/vmd1xaqfgbfza8xp9cf6hjnla" + } + ] + } + ], "card": { - "button": {}, - "image": {} + "button": { + "text": "Montar minha boneca", + "href": "/mini-me" + }, + "image": { + "mobile": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/aabde690-2705-4cad-8fed-7581caaebf15/mini-me-footer-card-mobi.png", + "desktop": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/90fd39dd-9090-4264-95fa-0409f2c28c4f/mini-me-footer-card-desk.png", + "alt": " Menina sorridente segura boneca de cabelos amarelos e vestido azul, em frente a fundo azul claro com detalhes geométricos." + }, + "title": "Faça a sua boneca", + "description": "A brincadeira começa bem antes de receber o presente! Customize sua Mini me do seu jeitinho!", + "badge": "Mini me" }, - "tecnologiesLogo": {}, - "cardFlags": [] + "tecnologiesLogo": { + "econverse": { + "0": "h", + "1": "t", + "2": "t", + "3": "p", + "4": "s", + "5": ":", + "6": "/", + "7": "/", + "8": "d", + "9": "e", + "10": "c", + "11": "o", + "12": "-", + "13": "s", + "14": "i", + "15": "t", + "16": "e", + "17": "s", + "18": "-", + "19": "a", + "20": "s", + "21": "s", + "22": "e", + "23": "t", + "24": "s", + "25": ".", + "26": "s", + "27": "3", + "28": ".", + "29": "s", + "30": "a", + "31": "-", + "32": "e", + "33": "a", + "34": "s", + "35": "t", + "36": "-", + "37": "1", + "38": ".", + "39": "a", + "40": "m", + "41": "a", + "42": "z", + "43": "o", + "44": "n", + "45": "a", + "46": "w", + "47": "s", + "48": ".", + "49": "c", + "50": "o", + "51": "m", + "52": "/", + "53": "a", + "54": "l", + "55": "p", + "56": "h", + "57": "a", + "58": "b", + "59": "e", + "60": "t", + "61": "o", + "62": "/", + "63": "7", + "64": "3", + "65": "1", + "66": "2", + "67": "8", + "68": "3", + "69": "0", + "70": "e", + "71": "-", + "72": "3", + "73": "4", + "74": "9", + "75": "e", + "76": "-", + "77": "4", + "78": "d", + "79": "9", + "80": "0", + "81": "-", + "82": "8", + "83": "9", + "84": "d", + "85": "9", + "86": "-", + "87": "2", + "88": "5", + "89": "8", + "90": "4", + "91": "5", + "92": "8", + "93": "0", + "94": "d", + "95": "0", + "96": "d", + "97": "7", + "98": "3", + "99": "/", + "100": "e", + "101": "c", + "102": "o", + "103": "n", + "104": "v", + "105": "e", + "106": "r", + "107": "s", + "108": "e", + "109": ".", + "110": "s", + "111": "v", + "112": "g", + "image": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/7312830e-349e-4d90-89d9-2584580d0d73/econverse.svg", + "url": "https://www.econverse.com.br/" + }, + "vtex": { + "0": "h", + "1": "t", + "2": "t", + "3": "p", + "4": "s", + "5": ":", + "6": "/", + "7": "/", + "8": "d", + "9": "e", + "10": "c", + "11": "o", + "12": "-", + "13": "s", + "14": "i", + "15": "t", + "16": "e", + "17": "s", + "18": "-", + "19": "a", + "20": "s", + "21": "s", + "22": "e", + "23": "t", + "24": "s", + "25": ".", + "26": "s", + "27": "3", + "28": ".", + "29": "s", + "30": "a", + "31": "-", + "32": "e", + "33": "a", + "34": "s", + "35": "t", + "36": "-", + "37": "1", + "38": ".", + "39": "a", + "40": "m", + "41": "a", + "42": "z", + "43": "o", + "44": "n", + "45": "a", + "46": "w", + "47": "s", + "48": ".", + "49": "c", + "50": "o", + "51": "m", + "52": "/", + "53": "a", + "54": "l", + "55": "p", + "56": "h", + "57": "a", + "58": "b", + "59": "e", + "60": "t", + "61": "o", + "62": "/", + "63": "8", + "64": "8", + "65": "6", + "66": "3", + "67": "f", + "68": "9", + "69": "4", + "70": "d", + "71": "-", + "72": "9", + "73": "c", + "74": "5", + "75": "5", + "76": "-", + "77": "4", + "78": "3", + "79": "5", + "80": "c", + "81": "-", + "82": "a", + "83": "4", + "84": "4", + "85": "e", + "86": "-", + "87": "2", + "88": "9", + "89": "8", + "90": "a", + "91": "2", + "92": "2", + "93": "0", + "94": "1", + "95": "c", + "96": "3", + "97": "d", + "98": "7", + "99": "/", + "100": "v", + "101": "t", + "102": "e", + "103": "x", + "104": ".", + "105": "s", + "106": "v", + "107": "g", + "url": "https://vtex.com/", + "image": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/8863f94d-9c55-435c-a44e-298a2201c3d7/vtex.svg" + } + }, + "cardFlags": [ + { + "title": "Visa", + "image": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/6d922ffa-f80b-4081-98d6-fea215301026/visa.svg" + }, + { + "title": "MasterCard", + "image": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/eede3cad-6853-4626-8793-e7d310bb0413/mastercard.svg" + }, + { + "title": "Dinners Club" + }, + { + "image": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/69596a10-a73d-4985-984a-ed50a29bf0a9/elo.svg", + "title": "Elo" + }, + { + "image": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/00c5bc36-08de-4834-80f2-c9f28f802bda/ame.svg", + "title": "Ame" + }, + { + "title": "PIX", + "image": "https://deco-sites-assets.s3.sa-east-1.amazonaws.com/alphabeto/d0309547-35a6-4b9f-bad2-09aec8b815f3/pix.svg" + } + ], + "copyright": "Copyright {{year}} - Todos os Direitos Reservados J.M.F. COMERCIO DE ROUPAS LTDA CNPJ: 10.657.141/0027-74 " } \ No newline at end of file diff --git a/.vim/coc-settings.json b/.vim/coc-settings.json new file mode 100644 index 0000000..8f9653d --- /dev/null +++ b/.vim/coc-settings.json @@ -0,0 +1,10 @@ +{ + "deno.enable": true, + "deno.lint": true, + "deno.unstable": true, + "prettier.disableLanguages": [ + "typescript", + "javascript" + ], + "tsserver.enable": false +} diff --git a/components/footer/Card.tsx b/components/footer/Card.tsx new file mode 100644 index 0000000..e1d4581 --- /dev/null +++ b/components/footer/Card.tsx @@ -0,0 +1,52 @@ +import { Picture, Source } from "apps/website/components/Picture.tsx"; +import { Card as CardProps } from "site/components/footer/types.ts"; +import { ButtonAnchor, ButtonType } from "site/components/ui/Button.tsx"; + +export function Card(props: CardProps) { + const { image } = props; + + return ( +
+ + + + {image.alt} + +
+ {props.badge && ( + + {props.badge} + + )} +

+ {props.title} +

+

+ {props.description} +

+ + {props.button.text} + +
+
+ ); +} diff --git a/components/footer/MenusAndCardDesktop.tsx b/components/footer/MenusAndCardDesktop.tsx new file mode 100644 index 0000000..749fd67 --- /dev/null +++ b/components/footer/MenusAndCardDesktop.tsx @@ -0,0 +1,88 @@ +import Image from "apps/website/components/Image.tsx"; +import { Card } from "site/components/footer/Card.tsx"; +import { + Card as CardProps, + Column as ColumnProps, + Menu as MenuProps, + TecnologiesLogo, +} from "site/components/footer/types.ts"; + +interface Props { + columns: ColumnProps[]; + card: CardProps; + tecnologiesLogo: TecnologiesLogo; +} + +function Menu(props: MenuProps) { + const titleContent = props.href + ? {props.title} + : props.title; + + return ( + + ); +} + +function Column(props: ColumnProps) { + return ( +
+ + {props.socialLogos?.length != null && ( + + )} +
+ ); +} + +export default function MenusAndCardDesktop(props: Props) { + return ( +
+
+
+ {props.columns.map((column) => )} +
+ +
+ +
+ ); +} diff --git a/components/footer/MenusAndCardMobile.tsx b/components/footer/MenusAndCardMobile.tsx new file mode 100644 index 0000000..c3f3783 --- /dev/null +++ b/components/footer/MenusAndCardMobile.tsx @@ -0,0 +1,134 @@ +import { useScript } from "@deco/deco/hooks"; +import Image from "apps/website/components/Image.tsx"; +import { Card } from "site/components/footer/Card.tsx"; +import { + Card as CardProps, + Column as ColumnProps, + Menu as MenuProps, +} from "site/components/footer/types.ts"; +import Icon from "site/components/ui/Icon.tsx"; +import { useId } from "site/sdk/useId.ts"; + +interface Props { + columns: ColumnProps[]; + card: CardProps; +} + +export interface ExtendedMenuProps extends MenuProps { + id: string; +} + +const handleToogle = (menus: ExtendedMenuProps[]) => { + menus.map((menu) => { + const menuElement = document.getElementById(menu.id); + if (!menuElement) return; + const button = menuElement.querySelector("button"); + + const itens = menuElement.querySelector("ul"); + if (!itens || !button) return; + + button.addEventListener("click", () => { + const visibleIcon = menuElement.querySelector(".block"); + const hiddenIcon = menuElement.querySelector(".hidden"); + if (!visibleIcon || !hiddenIcon) return; + const operation = itens.style.height === "0px" ? "open" : "close"; + visibleIcon.classList.toggle("block"); + visibleIcon.classList.toggle("hidden"); + hiddenIcon.classList.toggle("block"); + hiddenIcon.classList.toggle("hidden"); + + if (operation === "close") { + itens.style.height = "0px"; + } else { + itens.style.height = itens.scrollHeight + "px"; + } + }); + const link = button.querySelector("a"); + if (!link) return; + link.addEventListener("click", (ev) => ev.stopPropagation()); + }); +}; + +function Menu(props: ExtendedMenuProps) { + const titleContent = props.href + ? ( + + {props.title} + + ) + : ( + + {props.title} + + ); + + return ( + + ); +} + +export default function MenusAndCardMobile(props: Props) { + const allMenus = props.columns.map((column) => column.menus).flat().map( + (menu) => ({ + ...menu, + id: useId(), + }), + ); + const allSocialLogos = props.columns.map((column) => column.socialLogos ?? []) + .flat(); + + return ( +
+ + {allSocialLogos.length != null && ( + + )} + +
+ {allMenus.map((menu) => )} +