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