diff --git a/bun.lockb b/bun.lockb
index 42f5785..8b9f981 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index 708dcf1..94cab45 100644
--- a/package.json
+++ b/package.json
@@ -11,25 +11,23 @@
"prepare": "panda codegen && husky install"
},
"dependencies": {
- "@fontsource/open-sans": "^5.0.12",
+ "@fontsource/open-sans": "^5.0.20",
"@fontsource/permanent-marker": "^5.0.8",
"@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-brands-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/react-fontawesome": "^0.2.0",
- "appwrite": "^13.0.0",
+ "appwrite": "^13.0.1",
"entgamers-panda-preset": "0.1.0",
- "formik": "^2.4.4",
- "framer-motion": "^10.16.4",
- "gsap": "^3.12.2",
+ "formik": "^2.4.5",
+ "framer-motion": "^10.16.16",
"isomorphic-fetch": "^3.0.0",
- "next": "13.4.19",
- "next-connect": "^1.0.0",
- "node-appwrite": "^11.0.0",
+ "next": "^14.0.4",
+ "node-appwrite": "^11.1.0",
"react": "18.2.0",
"react-dom": "18.2.0",
- "sharp": "^0.32.5",
- "yup": "^1.2.0"
+ "sharp": "^0.33.1",
+ "yup": "^1.3.3"
},
"devDependencies": {
"@commitlint/cli": "^18.4.3",
diff --git a/src/app/equipo/page.tsx b/src/app/equipo/page.tsx
index c099efb..50506a2 100644
--- a/src/app/equipo/page.tsx
+++ b/src/app/equipo/page.tsx
@@ -1,34 +1,12 @@
import Typography from '@/components/ui/Typography'
-import { css, cx } from '@/styled-system/css'
+import { css } from '@/styled-system/css'
import { Container } from '@/styled-system/jsx'
import { center } from '@/styled-system/patterns'
-import { button, card, iconButton } from '@/styled-system/recipes'
-import { type TeamMember } from '@/types/User'
-import { faFacebook, faInstagram, faTwitch, faTwitter, faYoutube } from '@fortawesome/free-brands-svg-icons'
-import { faGlobe } from '@fortawesome/free-solid-svg-icons'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import NextImage from 'next/image'
+import { button } from '@/styled-system/recipes'
import NextLink from 'next/link'
import { type FC } from 'react'
-const team: TeamMember[] = [
- {
- image: '/images/team/SrJuggernaut.png',
- name: 'SrJuggernaut',
- role: 'administrator',
- description: 'Soy desarrollador web y me gusta jugar videojuegos.',
- socialNetworks: [
- { url: 'https://www.facebook.com/SrJuggernaut', label: 'SrJuggernaut Facebook', icon: faFacebook },
- { url: 'https://twitter.com/SrJuggernaut', label: 'SrJuggernaut Twitter', icon: faTwitter },
- { url: 'https://youtube.com/juggernautplays', label: 'SrJuggernaut YouTube', icon: faYoutube },
- { url: 'https://twitch.tv/juggernautplays', label: 'SrJuggernaut Twitch', icon: faTwitch },
- { url: 'https://www.instagram.com/sr_juggernaut', label: 'SrJuggernaut Instagram', icon: faInstagram },
- { url: 'https://srjuggernaut.dev/', label: 'SrJuggernaut Website', icon: faGlobe }
- ]
- }
-]
-
-const EquipoPage: FC = () => {
+const EquipoPage: FC = async () => {
return (
Equipo
@@ -49,7 +27,7 @@ const EquipoPage: FC = () => {
flexWrap: 'wrap'
})}
>
- {team.map((member, index) => (
+ {/* {team.map((member, index) => (
{
- ))}
+ ))} */}
+
+
+
+ ¡Quiero ser administrador!
+
+
Moderadores
Los moderadores son los encargados de mantener el orden en los grupos de la comunidad, así como de ayudar a los usuarios a resolver sus dudas.
diff --git a/src/app/equipo/unirse/ApplyForm.tsx b/src/app/equipo/unirse/ApplyForm.tsx
index 13c03b2..78d05a3 100644
--- a/src/app/equipo/unirse/ApplyForm.tsx
+++ b/src/app/equipo/unirse/ApplyForm.tsx
@@ -1,19 +1,25 @@
'use client'
+import Alert from '@/components/ui/Alert'
import Button from '@/components/ui/Button'
import Typography from '@/components/ui/Typography'
import FormGroup from '@/components/ui/form/FormGroup'
import Input from '@/components/ui/form/Input'
+import TextArea from '@/components/ui/form/TextArea'
+import { createTeamApply } from '@/services/frontend/teamApply'
import { css } from '@/styled-system/css'
+import { type Alert as AlertType } from '@/types/feedback'
import { type TeamApplyData } from '@/types/teamApply'
import { faChevronRight } from '@fortawesome/free-solid-svg-icons'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { FontAwesomeIcon, type FontAwesomeIconProps } from '@fortawesome/react-fontawesome'
+import { AppwriteException } from 'appwrite'
import { useFormik } from 'formik'
import { AnimatePresence, motion } from 'framer-motion'
import { useSearchParams } from 'next/navigation'
-import { useEffect, type FC } from 'react'
+import { useEffect, useState, type FC } from 'react'
const ApplyForm: FC = () => {
const searchParams = useSearchParams()
+ const [alert, setAlert] = useState(undefined)
const formik = useFormik({
initialValues: {
@@ -23,8 +29,25 @@ const ApplyForm: FC = () => {
message: '',
role: 'administrator'
},
- onSubmit: (values) => {
- console.log(values)
+ onSubmit: async (values) => {
+ try {
+ await createTeamApply(values)
+ } catch (error) {
+ if (error instanceof AppwriteException) {
+ setAlert({
+ title: 'Error al enviar el formulario',
+ message: error.message,
+ severity: 'error'
+ })
+ return
+ }
+ console.error('Error al enviar el formulario', error)
+ setAlert({
+ severity: 'error',
+ title: 'Error al enviar el formulario',
+ message: 'Hubo un error al enviar el formulario, por favor, intenta nuevamente.'
+ })
+ }
}
})
useEffect(() => {
@@ -92,77 +115,126 @@ const ApplyForm: FC = () => {
gap: 'medium'
})}
>
-
-
- Nombre
-
- {formik.touched.name !== undefined && formik.errors.name !== undefined && (
-
- {formik.errors.name}
-
- )}
-
-
- Email
-
- {formik.touched.email !== undefined && formik.errors.email !== undefined && (
-
- {formik.errors.email}
-
- )}
-
-
- Nombre de Discord
-
- {formik.touched.discordName !== undefined && formik.errors.discordName !== undefined && (
-
- {formik.errors.discordName}
-
- )}
-
-
- Mensaje
-
- {formik.touched.message !== undefined && formik.errors.message !== undefined && (
-
- {formik.errors.message}
-
- )}
-
-
- Enviar
-
-
+ {alert.title !== undefined && (
+ {alert.title}
+ )}
+ {alert.message}
+
+ )}
+ {formik.submitCount > 0 && (
+
+ )
+ }
+
{
Requisitos
- Imparcialidad
+ Imparcialidad
La comunidad esta conformada por amigos y conocidos, por lo tanto es importante poder actuar de forma imparcial y responsable.
@@ -194,7 +266,7 @@ const ApplyForm: FC = () => {
Beneficios
- Experiencia
+ Experiencia
Uno de los objetivos de la comunidad es brindar experiencia en gestión y desarrollo de proyectos equiparable a un entorno laboral, que sea comprobable y útil.
@@ -216,7 +288,7 @@ const ApplyForm: FC = () => {
Requisitos
- Profesionalismo
+ Profesionalismo
La comunidad siempre intenta conseguir el mayor nivel de calidad en todos sus proyectos, por lo que buscamos gente dispuesta a otorgar este nivel de profesionalismo para el disfrute de la comunidad.
@@ -224,7 +296,7 @@ const ApplyForm: FC = () => {
Beneficios
- Apoyo
+ Apoyo
Puedes contar con el apoyo de la comunidad para tus proyectos, ya sea en forma de difusión, asesoramiento o recursos.
@@ -246,17 +318,17 @@ const ApplyForm: FC = () => {
Requisitos
- Profesionalismo
+ Profesionalismo
La comunidad siempre intenta conseguir el mayor nivel de calidad en todos sus proyectos, por lo que buscamos gente dispuesta a otorgar este nivel de profesionalismo para el disfrute de la comunidad.
- Constancia
+ Constancia
La comunidad busca gente que en sus posibilidades sea activa, que pueda estar al tanto de lo que pasa en ella.
- Proactividad
+ Proactividad
La comunidad esta en constante crecimiento, por eso, buscamos gente que ayude a buscar nuevas oportunidades para diferentes proyectos y actividades de interés a la comunidad.
@@ -264,12 +336,12 @@ const ApplyForm: FC = () => {
Beneficios
- Experiencia
+ Experiencia
Uno de los objetivos de la comunidad es brindar experiencia en gestión y desarrollo de proyectos equiparable a un entorno laboral, que sea comprobable y útil.
- Capacitación
+ Capacitación
La comunidad buscara dar capacitación a sus miembros en lo referido a herramientas y procedimientos utilizados.
@@ -283,4 +355,5 @@ const ApplyForm: FC = () => {
)
}
+
export default ApplyForm
diff --git a/src/components/ui/Alert.tsx b/src/components/ui/Alert.tsx
new file mode 100644
index 0000000..48c1292
--- /dev/null
+++ b/src/components/ui/Alert.tsx
@@ -0,0 +1,36 @@
+import { cx } from '@/styled-system/css'
+import { alert, type AlertVariantProps } from '@/styled-system/recipes/alert'
+import { type MergeOmitting } from '@/types/utilities'
+import { faTimes } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon, type FontAwesomeIconProps } from '@fortawesome/react-fontawesome'
+import { type ButtonHTMLAttributes, type DetailedHTMLProps, type FC, type HTMLAttributes } from 'react'
+
+export type AlertProps = MergeOmitting, HTMLDivElement>, AlertVariantProps>
+
+const Alert: FC = ({ children, className, ...props }) => {
+ const [alertArgs, allOtherProps] = alert.splitVariantProps(props)
+ return (
+
+ {children}
+
+ )
+}
+
+export type AlertCloseButtonProps = MergeOmitting, HTMLButtonElement>, AlertVariantProps>
+
+export const AlertCloseButton: FC = ({ children, className, ...props }) => {
+ const [alertArgs, allOtherProps] = alert.splitVariantProps(props)
+ return (
+
+ {children !== undefined ? children : }
+
+ )
+}
+
+export default Alert
diff --git a/src/components/ui/BackDrop.tsx b/src/components/ui/BackDrop.tsx
index 5e2a328..0cc89e9 100644
--- a/src/components/ui/BackDrop.tsx
+++ b/src/components/ui/BackDrop.tsx
@@ -13,30 +13,33 @@ const BackDrop: FC = ({ isOpen, onClickAway, children }) => {
if (typeof window === 'undefined') return null
return createPortal((
- {isOpen && (
- {
- if (event.target === event.currentTarget) {
- onClickAway()
- }
- }}
- transition={{ duration: 0.3, ease: 'easeInOut' }}
- initial={{ opacity: 0 }}
- animate={{ opacity: 1 }}
- exit={{ opacity: 0 }}
- >
- {children}
-
- )}
+ {isOpen
+ ? (
+ {
+ if (event.target === event.currentTarget) {
+ onClickAway()
+ }
+ }}
+ transition={{ duration: 0.3, ease: 'easeInOut' }}
+ initial={{ opacity: 0 }}
+ animate={{ opacity: 1 }}
+ exit={{ opacity: 0 }}
+ >
+ {children}
+
+ )
+ : undefined
+ }
), document.body)
}
diff --git a/src/components/ui/form/TextArea.tsx b/src/components/ui/form/TextArea.tsx
new file mode 100644
index 0000000..1efb2d9
--- /dev/null
+++ b/src/components/ui/form/TextArea.tsx
@@ -0,0 +1,32 @@
+import { css, cx } from '@/styled-system/css'
+import { input, type InputVariantProps } from '@/styled-system/recipes/input'
+import { type MergeOmitting } from '@/types/utilities'
+import { type DetailedHTMLProps, type FC, type TextareaHTMLAttributes } from 'react'
+
+export type InputProps = MergeOmitting, HTMLTextAreaElement>, InputVariantProps>
+
+const TextArea: FC = ({ className, onChange, ...props }) => {
+ const [textAreaCss, rest] = input.splitVariantProps(props)
+ return (
+