diff --git a/package-lock.json b/package-lock.json index 54fcf118..073deb7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1570,40 +1570,6 @@ "strip-ansi": "^7.0.1" } }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, "strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", @@ -1613,23 +1579,6 @@ "ansi-regex": "^6.0.1" } }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - } - } - }, "wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -1640,60 +1589,6 @@ "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } } } }, @@ -12584,6 +12479,17 @@ "strip-ansi": "^6.0.1" } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, "string.prototype.matchall": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", @@ -12672,6 +12578,15 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -13722,6 +13637,17 @@ "strip-ansi": "^6.0.0" } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/src/atoms/Icons/Star.tsx b/src/atoms/Icons/Star.tsx new file mode 100644 index 00000000..9dc8ad7b --- /dev/null +++ b/src/atoms/Icons/Star.tsx @@ -0,0 +1,16 @@ +import { Base, BaseProps } from './Base' + +export function Star(props: BaseProps): JSX.Element { + return ( + + + + ) +} + +Star.displayName = 'Star' diff --git a/src/atoms/Icons/index.tsx b/src/atoms/Icons/index.tsx index 72968ed7..e5a79506 100644 --- a/src/atoms/Icons/index.tsx +++ b/src/atoms/Icons/index.tsx @@ -14,6 +14,7 @@ export * from './Multimedia' export * from './Profile' export * from './Remote' export * from './Schedule' +export * from './Star' export * from './Time' export * from './TinyAlertInfo' export * from './TinyAlertError' diff --git a/src/index.ts b/src/index.ts index 310caf1f..2a25d267 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,6 +36,7 @@ export { Eventos } from './organisms/Events' export { Resources } from './organisms/Resources' export { CalendarDropdown, EventsList } from './organisms/Calendar' export { UserDropdown } from './organisms/User' +export { ShareAndReviewModal } from './organisms/LinkedinAndReview' export type { AccesibleProfileMenuProps, ProfileMenuItem } from './organisms/User' // Tema diff --git a/src/organisms/LinkedinAndReview/ShareAndReviewModal.tsx b/src/organisms/LinkedinAndReview/ShareAndReviewModal.tsx new file mode 100644 index 00000000..1dd65f7a --- /dev/null +++ b/src/organisms/LinkedinAndReview/ShareAndReviewModal.tsx @@ -0,0 +1,108 @@ +import { + Modal, + ModalOverlay, + ModalContent, + ModalContentProps, + IconButton, + IconButtonProps, + Flex, + FlexProps, +} from '@chakra-ui/react' +import { useEffect, useState } from 'react' + +import { vars } from '@theme' + +import { CustomCloseIcon } from './components/CustomCloseIcon' +import { InitialShareContent } from './components/InitialShareContent' +import { AfterShareContent } from './components/AfterShareContent' + +const StyledModalContent = ModalContent as React.FC +const StyledIconButton = IconButton as React.FC +const StyledFlex = Flex as React.FC + +export interface ShareAndReviewProps { + isOpen: boolean + onClose: () => void + onContinue?: () => void + onLeaveReview?: () => void +} + +export const ShareAndReviewModal = ({ + isOpen, + onClose, + onContinue, + onLeaveReview, +}: ShareAndReviewProps): JSX.Element => { + const [hasClickedLinkedin, setHasClickedLinkedin] = useState(false) + + // Resetear el estado cada vez que se abre o cierra la modal + useEffect(() => { + if (!isOpen) { + setHasClickedLinkedin(false) + } + }, [isOpen]) + + const handleLinkedinClick: () => void = () => { + // 1. Ejecutamos la acción original de LinkedIn (abrir la nueva pestaña) + if (onContinue) { + onContinue() + } + + // 2. Aplicamos un pequeño timeout (ej: 400ms) para reemplazar el botón por el texto + // Esto da tiempo a que se registre la acción antes de cambiar la UI visualmente + setTimeout(() => { + setHasClickedLinkedin(true) + }, 400) + } + + return ( + + + + + } + onClick={onClose} + variant="ghost" + size="sm" + h="auto" + minW="16px" + position="absolute" + top="16px" + right="16px" + _hover={{ + background: 'none', + }} + _focus={{ + boxShadow: 'none', + }} + _focusVisible={{ + boxShadow: `0 0 0 3px ${vars('colors-alert-deepSkyBlue')} inset`, + }} + /> + + + {!hasClickedLinkedin ? ( + + ) : ( + + )} + + + + ) +} diff --git a/src/organisms/LinkedinAndReview/components/AfterShareContent.tsx b/src/organisms/LinkedinAndReview/components/AfterShareContent.tsx new file mode 100644 index 00000000..c389bffa --- /dev/null +++ b/src/organisms/LinkedinAndReview/components/AfterShareContent.tsx @@ -0,0 +1,70 @@ +import { Text, TextProps, Flex, FlexProps, Image, ImageProps } from '@chakra-ui/react' + +import { BtnLink, BtnPrimary } from '@molecules' +import { vars } from '@theme' + +import { Star } from '@/atoms/Icons' + +const StyledImage = Image as React.FC +const StyledFlex = Flex as React.FC +const StyledText = Text as React.FC + +export interface AfterShareContentProps { + onClose: () => void + onLeaveReview?: () => void +} + +export const AfterShareContent = ({ + onClose, + onLeaveReview, +}: AfterShareContentProps): JSX.Element => { + return ( + + + + ¿Ya lo compartiste en LinkedIn? + + + Ahora cuéntanos qué tal fue aprender con nosotros. Tu opinión ayuda a otros + como tú a dar el primer paso. + + }> + Dejar mi opinión + + + Quizás más tarde + + + ) +} diff --git a/src/organisms/LinkedinAndReview/components/CustomCloseIcon.tsx b/src/organisms/LinkedinAndReview/components/CustomCloseIcon.tsx new file mode 100644 index 00000000..3ab7e524 --- /dev/null +++ b/src/organisms/LinkedinAndReview/components/CustomCloseIcon.tsx @@ -0,0 +1,14 @@ +import { Base, BaseProps } from '@/atoms/Icons/Base' + +export function CustomCloseIcon(props: BaseProps): JSX.Element { + return ( + + + + ) +} diff --git a/src/organisms/LinkedinAndReview/components/InitialShareContent.tsx b/src/organisms/LinkedinAndReview/components/InitialShareContent.tsx new file mode 100644 index 00000000..f4319a56 --- /dev/null +++ b/src/organisms/LinkedinAndReview/components/InitialShareContent.tsx @@ -0,0 +1,99 @@ +import { + Text, + TextProps, + Divider, + DividerProps, + Link, + LinkProps, + Flex, + FlexProps, + Image, + ImageProps, +} from '@chakra-ui/react' + +import { Star } from '@/atoms/Icons' +import { BtnPrimary } from '@/molecules' +import { vars } from '@theme' + +const StyledImage = Image as React.FC +const StyledFlex = Flex as React.FC +const StyledText = Text as React.FC +const StyledDivider = Divider as React.FC +const StyledLink = Link as React.FC + +interface InitialShareContentProps { + handleLinkedinClick: () => void + onLeaveReview?: () => void +} + +export const InitialShareContent = ({ + handleLinkedinClick, + onLeaveReview, +}: InitialShareContentProps): JSX.Element => { + return ( + <> + + + + + ¡Qué bueno que quieras compartirlo! + + + Aprobaste tu curso. Vamos a mostrarlo en tu LinkedIn. + + + + Continuar a LinkedIn + + + + + Ya que estás aquí + + + + + ¿Qué tal fue aprender con nosotros? + + + + + + Dejar mi opinión + + + + ) +} diff --git a/src/organisms/LinkedinAndReview/index.ts b/src/organisms/LinkedinAndReview/index.ts new file mode 100644 index 00000000..31b7ae25 --- /dev/null +++ b/src/organisms/LinkedinAndReview/index.ts @@ -0,0 +1 @@ +export { ShareAndReviewModal } from './ShareAndReviewModal' diff --git a/src/organisms/index.ts b/src/organisms/index.ts index 04530798..abcc0204 100644 --- a/src/organisms/index.ts +++ b/src/organisms/index.ts @@ -6,3 +6,4 @@ export * from './Resources' export * from './Calendar' export * from './Modals' export * from './User' +export * from './LinkedinAndReview' diff --git a/tsconfig.types.json b/tsconfig.types.json index 3416c081..9d6b13ba 100644 --- a/tsconfig.types.json +++ b/tsconfig.types.json @@ -7,6 +7,7 @@ "outDir": "dist" }, "include": [ - "src/index.ts" + "src/index.ts", + "src/vite-env.d.ts" ] } \ No newline at end of file