@imansi/templates 0.1.0
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/LICENSE +21 -0
- package/README.md +557 -0
- package/package.json +35 -0
- package/src/auth/ForgotPasswordPage.jsx +176 -0
- package/src/auth/LoginPage.jsx +265 -0
- package/src/auth/RegisterPage.jsx +302 -0
- package/src/auth/ResetPasswordPage.jsx +158 -0
- package/src/auth/Verify2FAPage.jsx +175 -0
- package/src/dashboard/BillingPage.jsx +345 -0
- package/src/dashboard/DashboardHome.jsx +246 -0
- package/src/dashboard/NotificationsPage.jsx +230 -0
- package/src/dashboard/ProfilePage.jsx +272 -0
- package/src/dashboard/SettingsPage.jsx +415 -0
- package/src/dashboard/UsersTablePage.jsx +317 -0
- package/src/extra/CareersPage.jsx +166 -0
- package/src/extra/ChangelogPage.jsx +127 -0
- package/src/extra/CheckoutPage.jsx +383 -0
- package/src/extra/ComingSoonPage.jsx +147 -0
- package/src/extra/ErrorPage.jsx +91 -0
- package/src/extra/InvoicePage.jsx +241 -0
- package/src/extra/LegalPage.jsx +115 -0
- package/src/extra/MaintenancePage.jsx +172 -0
- package/src/extra/OnboardingPage.jsx +197 -0
- package/src/extra/StatusPage.jsx +181 -0
- package/src/index.js +53 -0
- package/src/layouts/AuthLayout.jsx +104 -0
- package/src/layouts/DashboardLayout.jsx +249 -0
- package/src/layouts/MarketingLayout.jsx +184 -0
- package/src/marketing/AboutPage.jsx +189 -0
- package/src/marketing/BlogPage.jsx +182 -0
- package/src/marketing/BlogPostPage.jsx +192 -0
- package/src/marketing/ContactPage.jsx +546 -0
- package/src/marketing/DocsPage.jsx +256 -0
- package/src/marketing/HomePage.jsx +702 -0
- package/src/marketing/LandingPage.jsx +755 -0
- package/src/marketing/PricingPage.jsx +205 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { Link } from 'react-router-dom';
|
|
3
|
+
import {
|
|
4
|
+
Alert,
|
|
5
|
+
Button,
|
|
6
|
+
Card,
|
|
7
|
+
CardContent,
|
|
8
|
+
Input,
|
|
9
|
+
Label,
|
|
10
|
+
} from '@imansi/ui';
|
|
11
|
+
import { AuthLayout } from '../layouts/AuthLayout.jsx';
|
|
12
|
+
|
|
13
|
+
export function ForgotPasswordPage({
|
|
14
|
+
title = '¿Olvidaste tu contraseña?',
|
|
15
|
+
subtitle = 'Ingresá tu correo y te enviamos un link para restablecerla.',
|
|
16
|
+
submitText = 'Enviar link',
|
|
17
|
+
submitLoadingText = 'Enviando...',
|
|
18
|
+
emailLabel = 'Correo electrónico',
|
|
19
|
+
successTitle = 'Revisá tu correo',
|
|
20
|
+
successMessage = 'Si el correo está registrado, te enviamos un link para restablecer tu contraseña. Revisá tu bandeja de entrada y la carpeta de spam.',
|
|
21
|
+
|
|
22
|
+
backToLoginHref = '/login',
|
|
23
|
+
backToLoginText = 'Volver al inicio de sesión',
|
|
24
|
+
|
|
25
|
+
brandName,
|
|
26
|
+
brandTagline,
|
|
27
|
+
brandLogo,
|
|
28
|
+
|
|
29
|
+
onSubmit,
|
|
30
|
+
error: externalError,
|
|
31
|
+
success: externalSuccess = false,
|
|
32
|
+
loading = false,
|
|
33
|
+
|
|
34
|
+
footer,
|
|
35
|
+
className,
|
|
36
|
+
}) {
|
|
37
|
+
const [correo, setCorreo] = useState('');
|
|
38
|
+
const [localError, setLocalError] = useState(null);
|
|
39
|
+
const [localSuccess, setLocalSuccess] = useState(false);
|
|
40
|
+
|
|
41
|
+
const showingSuccess = externalSuccess || localSuccess;
|
|
42
|
+
const error = localError || externalError;
|
|
43
|
+
|
|
44
|
+
async function handleSubmit(e) {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
setLocalError(null);
|
|
47
|
+
|
|
48
|
+
if (!correo) {
|
|
49
|
+
setLocalError('Ingresá tu correo electrónico.');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (onSubmit) {
|
|
54
|
+
const result = await onSubmit({ correo });
|
|
55
|
+
if (result?.ok) setLocalSuccess(true);
|
|
56
|
+
} else {
|
|
57
|
+
setLocalSuccess(true);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<AuthLayout
|
|
63
|
+
brandName={brandName}
|
|
64
|
+
brandTagline={brandTagline}
|
|
65
|
+
brandLogo={brandLogo}
|
|
66
|
+
className={className}
|
|
67
|
+
>
|
|
68
|
+
<div className="lg:hidden flex items-center gap-3 justify-center mb-6">
|
|
69
|
+
{brandLogo || (
|
|
70
|
+
<div className="h-10 w-10 rounded-lg bg-primary text-primary-foreground flex items-center justify-center font-bold">
|
|
71
|
+
{brandName?.charAt(0) || 'I'}
|
|
72
|
+
</div>
|
|
73
|
+
)}
|
|
74
|
+
<span className="text-h4 font-semibold">{brandName}</span>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<Card className="shadow-lg border-border/50">
|
|
78
|
+
<CardContent className="p-6 sm:p-7">
|
|
79
|
+
<div className="space-y-5">
|
|
80
|
+
{showingSuccess ? (
|
|
81
|
+
<>
|
|
82
|
+
<div className="space-y-1.5 text-center sm:text-left">
|
|
83
|
+
<div className="inline-flex h-12 w-12 items-center justify-center rounded-full bg-success/10 text-success">
|
|
84
|
+
<svg
|
|
85
|
+
width="22"
|
|
86
|
+
height="22"
|
|
87
|
+
viewBox="0 0 24 24"
|
|
88
|
+
fill="none"
|
|
89
|
+
stroke="currentColor"
|
|
90
|
+
strokeWidth="2.5"
|
|
91
|
+
strokeLinecap="round"
|
|
92
|
+
strokeLinejoin="round"
|
|
93
|
+
>
|
|
94
|
+
<polyline points="4,12 10,18 20,6" />
|
|
95
|
+
</svg>
|
|
96
|
+
</div>
|
|
97
|
+
<h1 className="text-h3 font-semibold tracking-tight">
|
|
98
|
+
{successTitle}
|
|
99
|
+
</h1>
|
|
100
|
+
<p className="text-small text-muted-foreground leading-snug">
|
|
101
|
+
{successMessage}
|
|
102
|
+
</p>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
{backToLoginHref && (
|
|
106
|
+
<Button variant="outline" fullWidth asChild>
|
|
107
|
+
<Link to={backToLoginHref}>{backToLoginText}</Link>
|
|
108
|
+
</Button>
|
|
109
|
+
)}
|
|
110
|
+
</>
|
|
111
|
+
) : (
|
|
112
|
+
<>
|
|
113
|
+
<div className="space-y-1.5">
|
|
114
|
+
<h1 className="text-h3 font-semibold tracking-tight">
|
|
115
|
+
{title}
|
|
116
|
+
</h1>
|
|
117
|
+
<p className="text-small text-muted-foreground leading-snug">
|
|
118
|
+
{subtitle}
|
|
119
|
+
</p>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
{error && (
|
|
123
|
+
<Alert variant="destructive" title="Error">
|
|
124
|
+
{error}
|
|
125
|
+
</Alert>
|
|
126
|
+
)}
|
|
127
|
+
|
|
128
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
129
|
+
<div className="space-y-1.5">
|
|
130
|
+
<Label
|
|
131
|
+
htmlFor="forgot-correo"
|
|
132
|
+
className="text-small font-medium"
|
|
133
|
+
>
|
|
134
|
+
{emailLabel}
|
|
135
|
+
</Label>
|
|
136
|
+
<Input
|
|
137
|
+
id="forgot-correo"
|
|
138
|
+
type="email"
|
|
139
|
+
placeholder="correo@ejemplo.com"
|
|
140
|
+
value={correo}
|
|
141
|
+
onChange={(e) => setCorreo(e.target.value)}
|
|
142
|
+
autoComplete="email"
|
|
143
|
+
autoFocus
|
|
144
|
+
disabled={loading}
|
|
145
|
+
/>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<Button type="submit" fullWidth disabled={loading}>
|
|
149
|
+
{loading ? submitLoadingText : submitText}
|
|
150
|
+
</Button>
|
|
151
|
+
</form>
|
|
152
|
+
</>
|
|
153
|
+
)}
|
|
154
|
+
</div>
|
|
155
|
+
</CardContent>
|
|
156
|
+
</Card>
|
|
157
|
+
|
|
158
|
+
{!showingSuccess && backToLoginHref && (
|
|
159
|
+
<p className="text-center text-small text-muted-foreground mt-5">
|
|
160
|
+
<Link
|
|
161
|
+
to={backToLoginHref}
|
|
162
|
+
className="text-primary font-medium hover:underline underline-offset-4"
|
|
163
|
+
>
|
|
164
|
+
{backToLoginText}
|
|
165
|
+
</Link>
|
|
166
|
+
</p>
|
|
167
|
+
)}
|
|
168
|
+
|
|
169
|
+
{footer && (
|
|
170
|
+
<p className="text-center text-caption text-muted-foreground mt-3 px-2">
|
|
171
|
+
{footer}
|
|
172
|
+
</p>
|
|
173
|
+
)}
|
|
174
|
+
</AuthLayout>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { Link } from 'react-router-dom';
|
|
3
|
+
import {
|
|
4
|
+
Alert,
|
|
5
|
+
Button,
|
|
6
|
+
Card,
|
|
7
|
+
CardContent,
|
|
8
|
+
Checkbox,
|
|
9
|
+
Input,
|
|
10
|
+
Label,
|
|
11
|
+
} from '@imansi/ui';
|
|
12
|
+
import { AuthLayout } from '../layouts/AuthLayout.jsx';
|
|
13
|
+
|
|
14
|
+
export function LoginPage({
|
|
15
|
+
title = 'Iniciar sesión',
|
|
16
|
+
subtitle = 'Bienvenido de nuevo. Ingresá tus credenciales para continuar.',
|
|
17
|
+
submitText = 'Entrar',
|
|
18
|
+
submitLoadingText = 'Entrando...',
|
|
19
|
+
emailLabel = 'Correo electrónico',
|
|
20
|
+
passwordLabel = 'Contraseña',
|
|
21
|
+
forgotPasswordText = '¿La olvidaste?',
|
|
22
|
+
registerText = '¿No tenés cuenta?',
|
|
23
|
+
registerLinkText = 'Crear una gratis',
|
|
24
|
+
rememberText = 'Recordarme por 30 días',
|
|
25
|
+
|
|
26
|
+
registerHref = '/registro',
|
|
27
|
+
forgotPasswordHref = '/recuperar',
|
|
28
|
+
|
|
29
|
+
brandName,
|
|
30
|
+
brandTagline,
|
|
31
|
+
brandLogo,
|
|
32
|
+
|
|
33
|
+
oauthProviders = [],
|
|
34
|
+
oauthTexts = {
|
|
35
|
+
github: 'Continuar con GitHub',
|
|
36
|
+
google: 'Continuar con Google',
|
|
37
|
+
o: 'o continuá con',
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
onSubmit,
|
|
41
|
+
onOAuthClick,
|
|
42
|
+
error: externalError,
|
|
43
|
+
loading = false,
|
|
44
|
+
showRememberMe = true,
|
|
45
|
+
|
|
46
|
+
footer,
|
|
47
|
+
className,
|
|
48
|
+
}) {
|
|
49
|
+
const [correo, setCorreo] = useState('');
|
|
50
|
+
const [contrasena, setContrasena] = useState('');
|
|
51
|
+
const [recordarme, setRecordarme] = useState(false);
|
|
52
|
+
const [localError, setLocalError] = useState(null);
|
|
53
|
+
|
|
54
|
+
async function handleSubmit(e) {
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
setLocalError(null);
|
|
57
|
+
|
|
58
|
+
if (!correo || !contrasena) {
|
|
59
|
+
setLocalError('Completá todos los campos.');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (onSubmit) {
|
|
64
|
+
await onSubmit({ correo, contrasena, recordarme });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function handleOAuth(provider) {
|
|
69
|
+
if (onOAuthClick) onOAuthClick(provider);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const error = localError || externalError;
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<AuthLayout
|
|
76
|
+
brandName={brandName}
|
|
77
|
+
brandTagline={brandTagline}
|
|
78
|
+
brandLogo={brandLogo}
|
|
79
|
+
className={className}
|
|
80
|
+
>
|
|
81
|
+
{/* Logo mobile */}
|
|
82
|
+
<div className="lg:hidden flex items-center gap-3 justify-center mb-6">
|
|
83
|
+
{brandLogo || (
|
|
84
|
+
<div className="h-10 w-10 rounded-lg bg-primary text-primary-foreground flex items-center justify-center font-bold">
|
|
85
|
+
{brandName?.charAt(0) || 'I'}
|
|
86
|
+
</div>
|
|
87
|
+
)}
|
|
88
|
+
<span className="text-h4 font-semibold">{brandName}</span>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<Card className="shadow-lg border-border/50">
|
|
92
|
+
<CardContent className="p-6 sm:p-7">
|
|
93
|
+
<div className="space-y-5">
|
|
94
|
+
{/* Encabezado */}
|
|
95
|
+
<div className="space-y-1.5">
|
|
96
|
+
<h1 className="text-h3 font-semibold tracking-tight">{title}</h1>
|
|
97
|
+
<p className="text-small text-muted-foreground leading-snug">
|
|
98
|
+
{subtitle}
|
|
99
|
+
</p>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
{/* Error */}
|
|
103
|
+
{error && (
|
|
104
|
+
<Alert variant="destructive" title="Error">
|
|
105
|
+
{error}
|
|
106
|
+
</Alert>
|
|
107
|
+
)}
|
|
108
|
+
|
|
109
|
+
{/* OAuth */}
|
|
110
|
+
{oauthProviders.length > 0 && (
|
|
111
|
+
<div className="space-y-4">
|
|
112
|
+
<div className="grid gap-2.5">
|
|
113
|
+
{oauthProviders.includes('github') && (
|
|
114
|
+
<Button
|
|
115
|
+
type="button"
|
|
116
|
+
variant="outline"
|
|
117
|
+
fullWidth
|
|
118
|
+
onClick={() => handleOAuth('github')}
|
|
119
|
+
disabled={loading}
|
|
120
|
+
>
|
|
121
|
+
<GitHubIcon />
|
|
122
|
+
{oauthTexts.github}
|
|
123
|
+
</Button>
|
|
124
|
+
)}
|
|
125
|
+
{oauthProviders.includes('google') && (
|
|
126
|
+
<Button
|
|
127
|
+
type="button"
|
|
128
|
+
variant="outline"
|
|
129
|
+
fullWidth
|
|
130
|
+
onClick={() => handleOAuth('google')}
|
|
131
|
+
disabled={loading}
|
|
132
|
+
>
|
|
133
|
+
<GoogleIcon />
|
|
134
|
+
{oauthTexts.google}
|
|
135
|
+
</Button>
|
|
136
|
+
)}
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
{/* Divisor */}
|
|
140
|
+
<div className="relative">
|
|
141
|
+
<div className="absolute inset-0 flex items-center">
|
|
142
|
+
<span className="w-full border-t border-border" />
|
|
143
|
+
</div>
|
|
144
|
+
<div className="relative flex justify-center text-caption uppercase">
|
|
145
|
+
<span className="bg-card px-3 text-muted-foreground tracking-widest text-[10px]">
|
|
146
|
+
{oauthTexts.o}
|
|
147
|
+
</span>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
)}
|
|
152
|
+
|
|
153
|
+
{/* Formulario */}
|
|
154
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
155
|
+
<div className="space-y-1.5">
|
|
156
|
+
<Label htmlFor="login-correo" className="text-small font-medium">
|
|
157
|
+
{emailLabel}
|
|
158
|
+
</Label>
|
|
159
|
+
<Input
|
|
160
|
+
id="login-correo"
|
|
161
|
+
type="email"
|
|
162
|
+
placeholder="correo@ejemplo.com"
|
|
163
|
+
value={correo}
|
|
164
|
+
onChange={(e) => setCorreo(e.target.value)}
|
|
165
|
+
autoComplete="email"
|
|
166
|
+
autoFocus
|
|
167
|
+
disabled={loading}
|
|
168
|
+
/>
|
|
169
|
+
</div>
|
|
170
|
+
|
|
171
|
+
<div className="space-y-1.5">
|
|
172
|
+
<div className="flex items-center justify-between">
|
|
173
|
+
<Label
|
|
174
|
+
htmlFor="login-contrasena"
|
|
175
|
+
className="text-small font-medium"
|
|
176
|
+
>
|
|
177
|
+
{passwordLabel}
|
|
178
|
+
</Label>
|
|
179
|
+
{forgotPasswordHref && (
|
|
180
|
+
<Link
|
|
181
|
+
to={forgotPasswordHref}
|
|
182
|
+
className="text-caption text-primary hover:underline underline-offset-4 font-medium"
|
|
183
|
+
>
|
|
184
|
+
{forgotPasswordText}
|
|
185
|
+
</Link>
|
|
186
|
+
)}
|
|
187
|
+
</div>
|
|
188
|
+
<Input
|
|
189
|
+
id="login-contrasena"
|
|
190
|
+
type="password"
|
|
191
|
+
placeholder="••••••••"
|
|
192
|
+
value={contrasena}
|
|
193
|
+
onChange={(e) => setContrasena(e.target.value)}
|
|
194
|
+
autoComplete="current-password"
|
|
195
|
+
disabled={loading}
|
|
196
|
+
/>
|
|
197
|
+
</div>
|
|
198
|
+
|
|
199
|
+
{showRememberMe && (
|
|
200
|
+
<div className="flex items-center gap-2.5">
|
|
201
|
+
<Checkbox
|
|
202
|
+
id="login-recordarme"
|
|
203
|
+
checked={recordarme}
|
|
204
|
+
onCheckedChange={setRecordarme}
|
|
205
|
+
disabled={loading}
|
|
206
|
+
/>
|
|
207
|
+
<Label
|
|
208
|
+
htmlFor="login-recordarme"
|
|
209
|
+
className="cursor-pointer font-normal text-small text-muted-foreground"
|
|
210
|
+
>
|
|
211
|
+
{rememberText}
|
|
212
|
+
</Label>
|
|
213
|
+
</div>
|
|
214
|
+
)}
|
|
215
|
+
|
|
216
|
+
<Button type="submit" fullWidth disabled={loading}>
|
|
217
|
+
{loading ? submitLoadingText : submitText}
|
|
218
|
+
</Button>
|
|
219
|
+
</form>
|
|
220
|
+
</div>
|
|
221
|
+
</CardContent>
|
|
222
|
+
</Card>
|
|
223
|
+
|
|
224
|
+
{/* Link a registro */}
|
|
225
|
+
{registerHref && (
|
|
226
|
+
<p className="text-center text-small text-muted-foreground mt-5">
|
|
227
|
+
{registerText}{' '}
|
|
228
|
+
<Link
|
|
229
|
+
to={registerHref}
|
|
230
|
+
className="text-primary font-medium hover:underline underline-offset-4"
|
|
231
|
+
>
|
|
232
|
+
{registerLinkText}
|
|
233
|
+
</Link>
|
|
234
|
+
</p>
|
|
235
|
+
)}
|
|
236
|
+
|
|
237
|
+
{/* Footer legal */}
|
|
238
|
+
{footer && (
|
|
239
|
+
<p className="text-center text-caption text-muted-foreground mt-3 px-2">
|
|
240
|
+
{footer}
|
|
241
|
+
</p>
|
|
242
|
+
)}
|
|
243
|
+
</AuthLayout>
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/* Iconos */
|
|
248
|
+
function GitHubIcon() {
|
|
249
|
+
return (
|
|
250
|
+
<svg viewBox="0 0 24 24" fill="currentColor" className="size-4">
|
|
251
|
+
<path d="M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.58.1.79-.25.79-.55v-1.94c-3.2.7-3.87-1.54-3.87-1.54-.52-1.33-1.28-1.68-1.28-1.68-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.55-.29-5.23-1.28-5.23-5.7 0-1.26.45-2.29 1.19-3.1-.12-.29-.52-1.46.11-3.05 0 0 .97-.31 3.18 1.18a11.05 11.05 0 0 1 5.8 0c2.2-1.49 3.17-1.18 3.17-1.18.63 1.59.23 2.76.11 3.05.74.81 1.19 1.84 1.19 3.1 0 4.43-2.69 5.4-5.25 5.69.41.35.78 1.05.78 2.12v3.15c0 .3.21.66.8.55C20.21 21.39 23.5 17.08 23.5 12 23.5 5.65 18.35.5 12 .5Z" />
|
|
252
|
+
</svg>
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function GoogleIcon() {
|
|
257
|
+
return (
|
|
258
|
+
<svg viewBox="0 0 24 24" className="size-4">
|
|
259
|
+
<path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.27-4.74 3.27-8.1Z" />
|
|
260
|
+
<path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84A11 11 0 0 0 12 23Z" />
|
|
261
|
+
<path fill="#FBBC05" d="M5.84 14.1a6.6 6.6 0 0 1 0-4.2V7.06H2.18a11 11 0 0 0 0 9.88l3.66-2.84Z" />
|
|
262
|
+
<path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.06l3.66 2.84C6.71 7.31 9.14 5.38 12 5.38Z" />
|
|
263
|
+
</svg>
|
|
264
|
+
);
|
|
265
|
+
}
|