@team14/cms-library 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cms-library.css +3 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +1369 -0
- package/package.json +4 -1
- package/dev/App.css +0 -184
- package/dev/App.tsx +0 -29
- package/dev/index.css +0 -114
- package/dev/index.html +0 -13
- package/dev/main.tsx +0 -10
- package/eslint.config.js +0 -23
- package/postcss.config.mjs +0 -5
- package/src/components/TestimonialCrousel/index.tsx +0 -115
- package/src/components/UI/CaseCard.tsx +0 -44
- package/src/components/UI/QuoteCard.tsx +0 -11
- package/src/components/UI/VideoCard.tsx +0 -11
- package/src/hooks/fetchTestimonials.tsx +0 -37
- package/src/index.ts +0 -4
- package/src/lib/index.tsx +0 -6
- package/src/types/common.ts +0 -18
- package/tsconfig.app.json +0 -25
- package/tsconfig.json +0 -7
- package/tsconfig.node.json +0 -24
- package/vite.config.ts +0 -38
- /package/{public → dist}/assets/hero.png +0 -0
- /package/{public → dist}/assets/react.svg +0 -0
- /package/{public → dist}/assets/vite.svg +0 -0
- /package/{public → dist}/favicon.svg +0 -0
- /package/{public → dist}/icons.svg +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@team14/cms-library",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.2",
|
|
5
5
|
"description": "Library of Components for CMS Web App.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
"author": "Team 14 - EmanuelFuneS",
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"homepage": "https://github.com/No-Country-simulation/S03-26-Equipo-14-Web-App-Development",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
14
17
|
"type": "module",
|
|
15
18
|
"main": "./dist/index.cjs.js",
|
|
16
19
|
"module": "./dist/index.es.js",
|
package/dev/App.css
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
.counter {
|
|
2
|
-
font-size: 16px;
|
|
3
|
-
padding: 5px 10px;
|
|
4
|
-
border-radius: 5px;
|
|
5
|
-
color: var(--accent);
|
|
6
|
-
background: var(--accent-bg);
|
|
7
|
-
border: 2px solid transparent;
|
|
8
|
-
transition: border-color 0.3s;
|
|
9
|
-
margin-bottom: 24px;
|
|
10
|
-
|
|
11
|
-
&:hover {
|
|
12
|
-
border-color: var(--accent-border);
|
|
13
|
-
}
|
|
14
|
-
&:focus-visible {
|
|
15
|
-
outline: 2px solid var(--accent);
|
|
16
|
-
outline-offset: 2px;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
.hero {
|
|
21
|
-
position: relative;
|
|
22
|
-
|
|
23
|
-
.base,
|
|
24
|
-
.framework,
|
|
25
|
-
.vite {
|
|
26
|
-
inset-inline: 0;
|
|
27
|
-
margin: 0 auto;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.base {
|
|
31
|
-
width: 170px;
|
|
32
|
-
position: relative;
|
|
33
|
-
z-index: 0;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
.framework,
|
|
37
|
-
.vite {
|
|
38
|
-
position: absolute;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.framework {
|
|
42
|
-
z-index: 1;
|
|
43
|
-
top: 34px;
|
|
44
|
-
height: 28px;
|
|
45
|
-
transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
|
|
46
|
-
scale(1.4);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.vite {
|
|
50
|
-
z-index: 0;
|
|
51
|
-
top: 107px;
|
|
52
|
-
height: 26px;
|
|
53
|
-
width: auto;
|
|
54
|
-
transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
|
|
55
|
-
scale(0.8);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
#center {
|
|
60
|
-
display: flex;
|
|
61
|
-
flex-direction: column;
|
|
62
|
-
gap: 25px;
|
|
63
|
-
place-content: center;
|
|
64
|
-
place-items: center;
|
|
65
|
-
flex-grow: 1;
|
|
66
|
-
|
|
67
|
-
@media (max-width: 1024px) {
|
|
68
|
-
padding: 32px 20px 24px;
|
|
69
|
-
gap: 18px;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
#next-steps {
|
|
74
|
-
display: flex;
|
|
75
|
-
border-top: 1px solid var(--border);
|
|
76
|
-
text-align: left;
|
|
77
|
-
|
|
78
|
-
& > div {
|
|
79
|
-
flex: 1 1 0;
|
|
80
|
-
padding: 32px;
|
|
81
|
-
@media (max-width: 1024px) {
|
|
82
|
-
padding: 24px 20px;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.icon {
|
|
87
|
-
margin-bottom: 16px;
|
|
88
|
-
width: 22px;
|
|
89
|
-
height: 22px;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
@media (max-width: 1024px) {
|
|
93
|
-
flex-direction: column;
|
|
94
|
-
text-align: center;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
#docs {
|
|
99
|
-
border-right: 1px solid var(--border);
|
|
100
|
-
|
|
101
|
-
@media (max-width: 1024px) {
|
|
102
|
-
border-right: none;
|
|
103
|
-
border-bottom: 1px solid var(--border);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
#next-steps ul {
|
|
108
|
-
list-style: none;
|
|
109
|
-
padding: 0;
|
|
110
|
-
display: flex;
|
|
111
|
-
gap: 8px;
|
|
112
|
-
margin: 32px 0 0;
|
|
113
|
-
|
|
114
|
-
.logo {
|
|
115
|
-
height: 18px;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
a {
|
|
119
|
-
color: var(--text-h);
|
|
120
|
-
font-size: 16px;
|
|
121
|
-
border-radius: 6px;
|
|
122
|
-
background: var(--social-bg);
|
|
123
|
-
display: flex;
|
|
124
|
-
padding: 6px 12px;
|
|
125
|
-
align-items: center;
|
|
126
|
-
gap: 8px;
|
|
127
|
-
text-decoration: none;
|
|
128
|
-
transition: box-shadow 0.3s;
|
|
129
|
-
|
|
130
|
-
&:hover {
|
|
131
|
-
box-shadow: var(--shadow);
|
|
132
|
-
}
|
|
133
|
-
.button-icon {
|
|
134
|
-
height: 18px;
|
|
135
|
-
width: 18px;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
@media (max-width: 1024px) {
|
|
140
|
-
margin-top: 20px;
|
|
141
|
-
flex-wrap: wrap;
|
|
142
|
-
justify-content: center;
|
|
143
|
-
|
|
144
|
-
li {
|
|
145
|
-
flex: 1 1 calc(50% - 8px);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
a {
|
|
149
|
-
width: 100%;
|
|
150
|
-
justify-content: center;
|
|
151
|
-
box-sizing: border-box;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
#spacer {
|
|
157
|
-
height: 88px;
|
|
158
|
-
border-top: 1px solid var(--border);
|
|
159
|
-
@media (max-width: 1024px) {
|
|
160
|
-
height: 48px;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
.ticks {
|
|
165
|
-
position: relative;
|
|
166
|
-
width: 100%;
|
|
167
|
-
|
|
168
|
-
&::before,
|
|
169
|
-
&::after {
|
|
170
|
-
content: '';
|
|
171
|
-
position: absolute;
|
|
172
|
-
top: -4.5px;
|
|
173
|
-
border: 5px solid transparent;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
&::before {
|
|
177
|
-
left: 0;
|
|
178
|
-
border-left-color: var(--border);
|
|
179
|
-
}
|
|
180
|
-
&::after {
|
|
181
|
-
right: 0;
|
|
182
|
-
border-right-color: var(--border);
|
|
183
|
-
}
|
|
184
|
-
}
|
package/dev/App.tsx
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import reactLogo from '../public/assets/react.svg';
|
|
2
|
-
import viteLogo from '../public/assets/vite.svg';
|
|
3
|
-
import heroImg from '../public/assets/hero.png';
|
|
4
|
-
import './App.css';
|
|
5
|
-
import TestimonialCarrousel from '../src/components/TestimonialCrousel';
|
|
6
|
-
|
|
7
|
-
function App() {
|
|
8
|
-
return (
|
|
9
|
-
<>
|
|
10
|
-
<section id="center">
|
|
11
|
-
<div className="hero">
|
|
12
|
-
<img src={heroImg} className="base" width="170" height="179" alt="" />
|
|
13
|
-
<img src={reactLogo} className="framework" alt="React logo" />
|
|
14
|
-
<img src={viteLogo} className="vite" alt="Vite logo" />
|
|
15
|
-
</div>
|
|
16
|
-
<div>
|
|
17
|
-
<h1>CMS Library</h1>
|
|
18
|
-
<h2>Preview Components</h2>
|
|
19
|
-
</div>
|
|
20
|
-
</section>
|
|
21
|
-
|
|
22
|
-
<TestimonialCarrousel apiKey="cms-api-key:DRAG954HBGPTuML0KvR0_g:Wt1_pWvPMg22Y0x6r6poJcNygqyVUU9FDTVJ-F60XeqW2o9Nkuux4ND_1XvHah3m8OL93JRPyv1cHO0dreVWYFLPk-QhGQlTlIEQ1PAF8WgwdZnf6Km4vKQu_rcx_CpWqQ2vx4RJT9Rx-VqjNjunIQ" />
|
|
23
|
-
|
|
24
|
-
<section id="spacer"></section>
|
|
25
|
-
</>
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default App;
|
package/dev/index.css
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/* index.css */
|
|
3
|
-
@import "tailwindcss";
|
|
4
|
-
:root {
|
|
5
|
-
--text: #6b6375;
|
|
6
|
-
--text-h: #08060d;
|
|
7
|
-
--bg: #fff;
|
|
8
|
-
--border: #e5e4e7;
|
|
9
|
-
--code-bg: #f4f3ec;
|
|
10
|
-
--accent: #aa3bff;
|
|
11
|
-
--accent-bg: rgba(170, 59, 255, 0.1);
|
|
12
|
-
--accent-border: rgba(170, 59, 255, 0.5);
|
|
13
|
-
--social-bg: rgba(244, 243, 236, 0.5);
|
|
14
|
-
--shadow:
|
|
15
|
-
rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;
|
|
16
|
-
|
|
17
|
-
--sans: system-ui, 'Segoe UI', Roboto, sans-serif;
|
|
18
|
-
--heading: system-ui, 'Segoe UI', Roboto, sans-serif;
|
|
19
|
-
--mono: ui-monospace, Consolas, monospace;
|
|
20
|
-
|
|
21
|
-
font: 18px/145% var(--sans);
|
|
22
|
-
letter-spacing: 0.18px;
|
|
23
|
-
color-scheme: light dark;
|
|
24
|
-
color: var(--text);
|
|
25
|
-
background: var(--bg);
|
|
26
|
-
font-synthesis: none;
|
|
27
|
-
text-rendering: optimizeLegibility;
|
|
28
|
-
-webkit-font-smoothing: antialiased;
|
|
29
|
-
-moz-osx-font-smoothing: grayscale;
|
|
30
|
-
|
|
31
|
-
@media (max-width: 1024px) {
|
|
32
|
-
font-size: 16px;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
@media (prefers-color-scheme: dark) {
|
|
37
|
-
:root {
|
|
38
|
-
--text: #9ca3af;
|
|
39
|
-
--text-h: #f3f4f6;
|
|
40
|
-
--bg: #16171d;
|
|
41
|
-
--border: #2e303a;
|
|
42
|
-
--code-bg: #1f2028;
|
|
43
|
-
--accent: #c084fc;
|
|
44
|
-
--accent-bg: rgba(192, 132, 252, 0.15);
|
|
45
|
-
--accent-border: rgba(192, 132, 252, 0.5);
|
|
46
|
-
--social-bg: rgba(47, 48, 58, 0.5);
|
|
47
|
-
--shadow:
|
|
48
|
-
rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
#social .button-icon {
|
|
52
|
-
filter: invert(1) brightness(2);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
#root {
|
|
57
|
-
width: 1126px;
|
|
58
|
-
max-width: 100%;
|
|
59
|
-
margin: 0 auto;
|
|
60
|
-
text-align: center;
|
|
61
|
-
border-inline: 1px solid var(--border);
|
|
62
|
-
min-height: 100svh;
|
|
63
|
-
display: flex;
|
|
64
|
-
flex-direction: column;
|
|
65
|
-
box-sizing: border-box;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
body {
|
|
69
|
-
margin: 0;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
h1,
|
|
73
|
-
h2 {
|
|
74
|
-
font-family: var(--heading);
|
|
75
|
-
font-weight: 500;
|
|
76
|
-
color: var(--text-h);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
h1 {
|
|
80
|
-
font-size: 56px;
|
|
81
|
-
letter-spacing: -1.68px;
|
|
82
|
-
margin: 32px 0;
|
|
83
|
-
@media (max-width: 1024px) {
|
|
84
|
-
font-size: 36px;
|
|
85
|
-
margin: 20px 0;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
h2 {
|
|
89
|
-
font-size: 24px;
|
|
90
|
-
line-height: 118%;
|
|
91
|
-
letter-spacing: -0.24px;
|
|
92
|
-
margin: 0 0 8px;
|
|
93
|
-
@media (max-width: 1024px) {
|
|
94
|
-
font-size: 20px;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
p {
|
|
98
|
-
margin: 0;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
code,
|
|
102
|
-
.counter {
|
|
103
|
-
font-family: var(--mono);
|
|
104
|
-
display: inline-flex;
|
|
105
|
-
border-radius: 4px;
|
|
106
|
-
color: var(--text-h);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
code {
|
|
110
|
-
font-size: 15px;
|
|
111
|
-
line-height: 135%;
|
|
112
|
-
padding: 4px 8px;
|
|
113
|
-
background: var(--code-bg);
|
|
114
|
-
}
|
package/dev/index.html
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>cms-library</title>
|
|
8
|
-
</head>
|
|
9
|
-
<body>
|
|
10
|
-
<div id="root"></div>
|
|
11
|
-
<script type="module" src="./main.tsx"></script>
|
|
12
|
-
</body>
|
|
13
|
-
</html>
|
package/dev/main.tsx
DELETED
package/eslint.config.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import js from '@eslint/js'
|
|
2
|
-
import globals from 'globals'
|
|
3
|
-
import reactHooks from 'eslint-plugin-react-hooks'
|
|
4
|
-
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
5
|
-
import tseslint from 'typescript-eslint'
|
|
6
|
-
import { defineConfig, globalIgnores } from 'eslint/config'
|
|
7
|
-
|
|
8
|
-
export default defineConfig([
|
|
9
|
-
globalIgnores(['dist']),
|
|
10
|
-
{
|
|
11
|
-
files: ['**/*.{ts,tsx}'],
|
|
12
|
-
extends: [
|
|
13
|
-
js.configs.recommended,
|
|
14
|
-
tseslint.configs.recommended,
|
|
15
|
-
reactHooks.configs.flat.recommended,
|
|
16
|
-
reactRefresh.configs.vite,
|
|
17
|
-
],
|
|
18
|
-
languageOptions: {
|
|
19
|
-
ecmaVersion: 2020,
|
|
20
|
-
globals: globals.browser,
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
])
|
package/postcss.config.mjs
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import type { ComponentProps, Testimonial } from '../../types/common';
|
|
2
|
-
import useFetchTestimonials from '../../hooks/fetchTestimonials';
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
|
|
5
|
-
import QuoteCard from '../UI/QuoteCard';
|
|
6
|
-
import VideoCard from '../UI/VideoCard';
|
|
7
|
-
import CaseCard from '../UI/CaseCard';
|
|
8
|
-
import { AnimatePresence, motion } from 'framer-motion';
|
|
9
|
-
import { cn } from '../../lib/index';
|
|
10
|
-
|
|
11
|
-
const variants = {
|
|
12
|
-
enter: (direction: number) => ({
|
|
13
|
-
x: direction > 0 ? 300 : -300,
|
|
14
|
-
opacity: 0,
|
|
15
|
-
}),
|
|
16
|
-
center: { x: 0, opacity: 1 },
|
|
17
|
-
exit: (direction: number) => ({
|
|
18
|
-
x: direction > 0 ? -300 : 300,
|
|
19
|
-
opacity: 0,
|
|
20
|
-
}),
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const TestimonialCarrousel = ({ apiKey, length = 2, className }: ComponentProps) => {
|
|
24
|
-
const { isLoading, testimonials } = useFetchTestimonials({ apiKey });
|
|
25
|
-
const [currentIndex, setCurrentIndex] = useState(0);
|
|
26
|
-
const [direction, setDirection] = useState(1);
|
|
27
|
-
|
|
28
|
-
const data = testimonials?.slice(0, length) ?? [];
|
|
29
|
-
|
|
30
|
-
const paginate = (newDirection: number) => {
|
|
31
|
-
setDirection(newDirection);
|
|
32
|
-
setCurrentIndex((prev) => (prev + newDirection + data.length) % data.length);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const renderCard = (testimonial: Testimonial) => {
|
|
36
|
-
switch (testimonial.type) {
|
|
37
|
-
case 'case':
|
|
38
|
-
return <CaseCard data={testimonial} />;
|
|
39
|
-
case 'video':
|
|
40
|
-
return <VideoCard data={testimonial} />;
|
|
41
|
-
default:
|
|
42
|
-
return <QuoteCard data={testimonial} />;
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<div className={cn("w-full flex flex-col my-10", className)}>
|
|
48
|
-
<div className="flex items-center justify-center px-4">
|
|
49
|
-
{isLoading ? (
|
|
50
|
-
<div className="text-muted-foreground">Cargando testimonios...</div>
|
|
51
|
-
) : (
|
|
52
|
-
<div className="w-full max-w-3xl flex flex-col gap-8">
|
|
53
|
-
{/* Card animada */}
|
|
54
|
-
<div className="min-h-70 flex items-center">
|
|
55
|
-
<AnimatePresence custom={direction} mode="wait">
|
|
56
|
-
<motion.div
|
|
57
|
-
key={currentIndex}
|
|
58
|
-
custom={direction}
|
|
59
|
-
variants={variants}
|
|
60
|
-
initial="enter"
|
|
61
|
-
animate="center"
|
|
62
|
-
exit="exit"
|
|
63
|
-
transition={{ duration: 0.5, ease: 'easeInOut' }}
|
|
64
|
-
className="w-full"
|
|
65
|
-
>
|
|
66
|
-
{data[currentIndex] && renderCard(data[currentIndex])}
|
|
67
|
-
</motion.div>
|
|
68
|
-
</AnimatePresence>
|
|
69
|
-
</div>
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
<div className="flex items-center justify-center gap-8">
|
|
73
|
-
<button
|
|
74
|
-
onClick={() => paginate(-1)}
|
|
75
|
-
className="w-11 h-11 flex items-center justify-center rounded-full border border-border bg-card hover:bg-accent hover:text-accent-foreground transition-colors shadow-sm"
|
|
76
|
-
aria-label="Anterior"
|
|
77
|
-
>
|
|
78
|
-
←
|
|
79
|
-
</button>
|
|
80
|
-
|
|
81
|
-
<div className="flex gap-3">
|
|
82
|
-
{data.map((_, idx) => (
|
|
83
|
-
<button
|
|
84
|
-
key={idx}
|
|
85
|
-
onClick={() => {
|
|
86
|
-
setDirection(idx - currentIndex);
|
|
87
|
-
setCurrentIndex(idx);
|
|
88
|
-
}}
|
|
89
|
-
className={cn(
|
|
90
|
-
"w-3.5 h-3.5 rounded-full transition-all",
|
|
91
|
-
idx === currentIndex
|
|
92
|
-
? "bg-primary scale-125"
|
|
93
|
-
: "bg-muted-foreground/30 hover:bg-muted-foreground/50"
|
|
94
|
-
)}
|
|
95
|
-
aria-label={`Ir al testimonio ${idx + 1}`}
|
|
96
|
-
/>
|
|
97
|
-
))}
|
|
98
|
-
</div>
|
|
99
|
-
|
|
100
|
-
<button
|
|
101
|
-
onClick={() => paginate(1)}
|
|
102
|
-
className="w-11 h-11 flex items-center justify-center rounded-full border border-border bg-card hover:bg-accent hover:text-accent-foreground transition-colors shadow-sm"
|
|
103
|
-
aria-label="Siguiente"
|
|
104
|
-
>
|
|
105
|
-
→
|
|
106
|
-
</button>
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
|
-
)}
|
|
110
|
-
</div>
|
|
111
|
-
</div>
|
|
112
|
-
);
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
export default TestimonialCarrousel;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { Testimonial } from '../../types/common';
|
|
2
|
-
import { cn } from '../../lib/index';
|
|
3
|
-
|
|
4
|
-
interface CaseCardProps {
|
|
5
|
-
data: Testimonial;
|
|
6
|
-
className?: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const CaseCard = ({ data, className }: CaseCardProps) => {
|
|
10
|
-
return (
|
|
11
|
-
<div
|
|
12
|
-
className={cn(
|
|
13
|
-
'border border-border bg-card text-card-foreground rounded-2xl p-8 shadow-sm',
|
|
14
|
-
'flex flex-col min-h-60',
|
|
15
|
-
className,
|
|
16
|
-
)}
|
|
17
|
-
>
|
|
18
|
-
<div className="flex-1 text-lg leading-relaxed text-foreground">
|
|
19
|
-
“{data.content}”
|
|
20
|
-
</div>
|
|
21
|
-
|
|
22
|
-
<div className="mt-8 flex items-center gap-4">
|
|
23
|
-
<div className="w-12 h-12 rounded-full bg-muted shrink-0 overflow-hidden border border-border">
|
|
24
|
-
{data.author_photo ? (
|
|
25
|
-
<img
|
|
26
|
-
src={data.author_photo}
|
|
27
|
-
alt={data.author}
|
|
28
|
-
className="w-full h-full object-cover"
|
|
29
|
-
/>
|
|
30
|
-
) : (
|
|
31
|
-
<div className="w-full h-full bg-primary/10" />
|
|
32
|
-
)}
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
<div>
|
|
36
|
-
<p className="font-semibold text-foreground">{data.author}</p>
|
|
37
|
-
<p className="text-sm text-muted-foreground">{data.author_role}</p>
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export default CaseCard;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
import type { Testimonial } from '../types/common';
|
|
3
|
-
|
|
4
|
-
interface useFetchTestimonialsProps {
|
|
5
|
-
apiKey?: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const useFetchTestimonials = ({ apiKey }: useFetchTestimonialsProps) => {
|
|
9
|
-
const [testimonials, setTestimonials] = useState<Testimonial[]>();
|
|
10
|
-
const [isLoading, setIsLoading] = useState<boolean>(true);
|
|
11
|
-
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
const fetchTestimonials = async () => {
|
|
14
|
-
if (!apiKey) return;
|
|
15
|
-
const result = await fetch(
|
|
16
|
-
'https://s03-26-equipo-14-web-app-development.onrender.com/embed',
|
|
17
|
-
{
|
|
18
|
-
method: 'Get',
|
|
19
|
-
headers: {
|
|
20
|
-
'x-embed-key': apiKey,
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
);
|
|
24
|
-
const response = await result.json();
|
|
25
|
-
if (response.success) setIsLoading(false);
|
|
26
|
-
setTestimonials(response.data);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
fetchTestimonials();
|
|
30
|
-
}, []);
|
|
31
|
-
return {
|
|
32
|
-
testimonials,
|
|
33
|
-
isLoading,
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export default useFetchTestimonials;
|
package/src/index.ts
DELETED
package/src/lib/index.tsx
DELETED
package/src/types/common.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export interface ComponentProps {
|
|
2
|
-
apiKey: string;
|
|
3
|
-
length?: number;
|
|
4
|
-
className?: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface Testimonial {
|
|
8
|
-
id: string;
|
|
9
|
-
type: string;
|
|
10
|
-
title: string;
|
|
11
|
-
content: string;
|
|
12
|
-
author: string;
|
|
13
|
-
author_photo: string;
|
|
14
|
-
author_role: string;
|
|
15
|
-
media_url: string;
|
|
16
|
-
media_description: string;
|
|
17
|
-
rating: string;
|
|
18
|
-
}
|
package/tsconfig.app.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
-
"target": "es2023",
|
|
5
|
-
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
|
6
|
-
"module": "esnext",
|
|
7
|
-
"types": ["vite/client"],
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
|
|
10
|
-
/* Bundler mode */
|
|
11
|
-
"moduleResolution": "bundler",
|
|
12
|
-
"allowImportingTsExtensions": true,
|
|
13
|
-
"verbatimModuleSyntax": true,
|
|
14
|
-
"moduleDetection": "force",
|
|
15
|
-
"noEmit": true,
|
|
16
|
-
"jsx": "react-jsx",
|
|
17
|
-
|
|
18
|
-
/* Linting */
|
|
19
|
-
"noUnusedLocals": true,
|
|
20
|
-
"noUnusedParameters": true,
|
|
21
|
-
"erasableSyntaxOnly": true,
|
|
22
|
-
"noFallthroughCasesInSwitch": true
|
|
23
|
-
},
|
|
24
|
-
"include": ["src", "dev"]
|
|
25
|
-
}
|