diff --git a/.env.example b/.env.example
index 32612d6..f306c51 100644
--- a/.env.example
+++ b/.env.example
@@ -1,7 +1,6 @@
# App variables
SITE_NAME="EntGamers"
-DISCORD_JOIN_WEBHOOK_URL="https://discord.com/api/webhooks/XXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# Deployment variables
@@ -14,4 +13,18 @@ DEPLOY_PATH=""
# Github actions variables
SSH_PRIVATE_KEY=""
-SSH_KNOWN_HOSTS=""
\ No newline at end of file
+SSH_KNOWN_HOSTS=""
+
+# Appwrite required variables
+
+NEXT_PUBLIC_APPWRITE_ENDPOINT=""
+NEXT_PUBLIC_APPWRITE_PROJECT_ID=""
+APPWRITE_API_KEY=""
+
+# Appwrite optional variables
+
+NEXT_PUBLIC_APPWRITE_DATABASE_ID=""
+NEXT_PUBLIC_APPWRITE_COLLECTION_ID=""
+NEXT_PUBLIC_APPWRITE_ADMIN_TEAM_ID=""
+NEXT_PUBLIC_APPWRITE_ADMIN_MODERATOR_TEAM_ID=""
+NEXT_PUBLIC_APPWRITE_ADMIN_COLLABORATOR_TEAM_ID=""
\ No newline at end of file
diff --git a/package.json b/package.json
index d93d3fc..2cdd481 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"@fortawesome/free-brands-svg-icons": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2",
"@fortawesome/react-fontawesome": "^0.2.0",
+ "appwrite": "^13.0.0",
"entgamers-panda-preset": "0.0.7",
"formik": "^2.4.4",
"framer-motion": "^10.16.4",
@@ -24,6 +25,7 @@
"isomorphic-fetch": "^3.0.0",
"next": "13.4.19",
"next-connect": "^1.0.0",
+ "node-appwrite": "^11.0.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"sharp": "^0.32.5",
diff --git a/src/app/Team.tsx b/src/app/Team.tsx
index 3017974..6c92e26 100644
--- a/src/app/Team.tsx
+++ b/src/app/Team.tsx
@@ -30,16 +30,14 @@ const team: TeamMember[] = [
const Team: FC = () => {
return (
-
))}
-
-
-
-
+
- Ver el equipo completo
-
-
- Únete al equipo
-
-
+
+ Ver el equipo completo
+
+
+ Únete al equipo
+
+
+
)
}
diff --git a/src/app/equipo/page.tsx b/src/app/equipo/page.tsx
index 5434fc2..c099efb 100644
--- a/src/app/equipo/page.tsx
+++ b/src/app/equipo/page.tsx
@@ -103,7 +103,7 @@ const EquipoPage: FC = () => {
¡Quiero ser moderador!
@@ -119,7 +119,7 @@ const EquipoPage: FC = () => {
¡Quiero ser colaborador!
diff --git a/src/app/equipo/unirse/ApplyForm.tsx b/src/app/equipo/unirse/ApplyForm.tsx
new file mode 100644
index 0000000..13c03b2
--- /dev/null
+++ b/src/app/equipo/unirse/ApplyForm.tsx
@@ -0,0 +1,286 @@
+'use client'
+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 { css } from '@/styled-system/css'
+import { type TeamApplyData } from '@/types/teamApply'
+import { faChevronRight } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { useFormik } from 'formik'
+import { AnimatePresence, motion } from 'framer-motion'
+import { useSearchParams } from 'next/navigation'
+import { useEffect, type FC } from 'react'
+
+const ApplyForm: FC = () => {
+ const searchParams = useSearchParams()
+
+ const formik = useFormik
({
+ initialValues: {
+ name: '',
+ email: '',
+ discordName: '',
+ message: '',
+ role: 'administrator'
+ },
+ onSubmit: (values) => {
+ console.log(values)
+ }
+ })
+ useEffect(() => {
+ if (searchParams.has('role')) {
+ formik.setFieldValue('role', searchParams.get('role'))
+ .catch((error) => {
+ console.error(error)
+ })
+ }
+ }, [])
+
+ return (
+
+ )
+}
+export default ApplyForm
diff --git a/src/app/equipo/unirse/page.tsx b/src/app/equipo/unirse/page.tsx
index 7d78e31..72a139a 100644
--- a/src/app/equipo/unirse/page.tsx
+++ b/src/app/equipo/unirse/page.tsx
@@ -1,7 +1,7 @@
import Typography from '@/components/ui/Typography'
-import { css } from '@/styled-system/css'
import { Container } from '@/styled-system/jsx'
import { type FC } from 'react'
+import ApplyForm from './ApplyForm'
const EquipoUnirsePage: FC = () => {
return (
@@ -10,21 +10,7 @@ const EquipoUnirsePage: FC = () => {
El equipo de EntGamers está formado por personas que se dedican a la administración de la comunidad, a la organización de eventos y a la creación de contenido. Aquí podrás enterarte cuales son las funciones de cada uno de los miembros del equipo y como puedes unirte a nosotros.
-
- Esta sección está en construcción. Puedes unirte contactándonos mediante nuestro
Servidor de Discord .
-
+
)
}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 68e5567..bdfc79d 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -2,9 +2,17 @@ import Clanes from '@/app/Clanes'
import Hero from '@/app/Hero'
import Social from '@/app/Social'
import Team from '@/app/Team'
+import { ensureRoles } from '@/services/backend/roles'
+import { ensureTeamApplyCollection } from '@/services/backend/teamApply'
import { type FC } from 'react'
-const HomePage: FC = () => {
+const ensureAll = async (): Promise => {
+ await ensureRoles()
+ await ensureTeamApplyCollection()
+}
+
+const HomePage: FC = async () => {
+ await ensureAll()
return (
<>
diff --git a/src/components/layout/Menu.tsx b/src/components/layout/Menu.tsx
index b5de733..a9f2130 100644
--- a/src/components/layout/Menu.tsx
+++ b/src/components/layout/Menu.tsx
@@ -1,5 +1,6 @@
import trees from '@/assets/icons/trees'
import BackDrop from '@/components/ui/BackDrop'
+import IconButton from '@/components/ui/IconButton'
import { css } from '@/styled-system/css'
import { iconButton } from '@/styled-system/recipes'
import { type IconDefinition } from '@fortawesome/fontawesome-common-types'
@@ -29,14 +30,11 @@ const Menu: FC = () => {
}, [])
return (
<>
- { setIsMenuOpen(!isMenuOpen) }}
>
-
+
, HTMLButtonElement>, ButtonVariantProps>
+
+export interface ButtonProps extends ComposedButtonProps {}
+
+const Button: FC = ({ children, className, ...rest }) => {
+ const [buttonRecipeArgs, allOtherButtonProps] = button.splitVariantProps(rest)
+ return (
+
+ {children}
+
+ )
+}
+
+export default Button
diff --git a/src/components/ui/IconButton.tsx b/src/components/ui/IconButton.tsx
new file mode 100644
index 0000000..25423ec
--- /dev/null
+++ b/src/components/ui/IconButton.tsx
@@ -0,0 +1,22 @@
+import { cx } from '@/styled-system/css'
+import { iconButton, type IconButtonVariantProps } from '@/styled-system/recipes/icon-button'
+import { type MergeOmitting } from '@/types/utilities'
+import React, { type FC } from 'react'
+
+type ComposedIconButtonProps = MergeOmitting, IconButtonVariantProps>
+
+export interface IconButtonProps extends ComposedIconButtonProps {}
+
+const IconButton: FC = ({ children, className, ...rest }) => {
+ const [iconButtonRecipeArgs, allOtherIconButtonProps] = iconButton.splitVariantProps(rest)
+ return (
+
+ {children}
+
+ )
+}
+
+export default IconButton
diff --git a/src/components/ui/form/FormGroup.tsx b/src/components/ui/form/FormGroup.tsx
new file mode 100644
index 0000000..72fc16e
--- /dev/null
+++ b/src/components/ui/form/FormGroup.tsx
@@ -0,0 +1,23 @@
+import { css, cx } from '@/styled-system/css'
+import { type DetailedHTMLProps, type FC, type HTMLAttributes, type ReactNode } from 'react'
+
+export interface FormGroupProps extends DetailedHTMLProps, HTMLDivElement> {
+ children: ReactNode
+}
+
+const FormGroup: FC = ({ children, className, ...props }) => {
+ return (
+
+ {children}
+
+ )
+}
+export default FormGroup
diff --git a/src/components/ui/form/Input.tsx b/src/components/ui/form/Input.tsx
new file mode 100644
index 0000000..e94561b
--- /dev/null
+++ b/src/components/ui/form/Input.tsx
@@ -0,0 +1,17 @@
+import { 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 InputHTMLAttributes } from 'react'
+
+export type InputProps = MergeOmitting, HTMLInputElement>, InputVariantProps>
+
+const Input: FC = ({ className, ...props }) => {
+ const [inputCss, rest] = input.splitVariantProps(props)
+ return (
+
+ )
+}
+export default Input
diff --git a/src/lib/appwrite.ts b/src/lib/appwrite.ts
new file mode 100644
index 0000000..8e7be23
--- /dev/null
+++ b/src/lib/appwrite.ts
@@ -0,0 +1,9 @@
+import { Client, Databases } from 'appwrite'
+
+export const appwriteClient = new Client()
+ .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT ?? '')
+ .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT ?? '')
+
+export const databases = new Databases(appwriteClient)
+
+export { ID } from 'appwrite'
diff --git a/src/lib/nodeAppwrite.ts b/src/lib/nodeAppwrite.ts
new file mode 100644
index 0000000..2d09cf0
--- /dev/null
+++ b/src/lib/nodeAppwrite.ts
@@ -0,0 +1,12 @@
+import { Client, Databases, Teams } from 'node-appwrite'
+
+export const clientNodeAppwrite = new Client()
+ .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT ?? '')
+ .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID ?? '')
+ .setKey(process.env.APPWRITE_API_KEY ?? '')
+
+export const databases = new Databases(clientNodeAppwrite)
+
+export const teams = new Teams(clientNodeAppwrite)
+
+export { Permission, Role } from 'node-appwrite'
diff --git a/src/services/backend/database.ts b/src/services/backend/database.ts
new file mode 100644
index 0000000..63c627c
--- /dev/null
+++ b/src/services/backend/database.ts
@@ -0,0 +1,18 @@
+import { databases } from '@/lib/nodeAppwrite'
+
+export const DATABASE_NAME = 'entgamers-website'
+export const DATABASE_ID = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID ?? DATABASE_NAME
+
+export const ensureDatabase = (() => {
+ let databaseEnsured = false
+ return async () => {
+ if (databaseEnsured) return
+ try {
+ await databases.get(DATABASE_ID)
+ } catch (error) {
+ await databases.create(DATABASE_ID, DATABASE_NAME)
+ } finally {
+ databaseEnsured = true
+ }
+ }
+})()
diff --git a/src/services/backend/roles.ts b/src/services/backend/roles.ts
new file mode 100644
index 0000000..00f31ad
--- /dev/null
+++ b/src/services/backend/roles.ts
@@ -0,0 +1,35 @@
+import { teams } from '@/lib/nodeAppwrite'
+import { type UserPreferences } from '@/types/User'
+
+export const ADMIN_TEAM_NAME = 'admin'
+export const ADMIN_TEAM_ID = process.env.NEXT_PUBLIC_APPWRITE_ADMIN_TEAM_ID ?? ADMIN_TEAM_NAME
+export const MODERATOR_TEAM_NAME = 'moderator'
+export const MODERATOR_TEAM_ID = process.env.NEXT_PUBLIC_APPWRITE_MODERATOR_TEAM_ID ?? MODERATOR_TEAM_NAME
+export const COLLABORATOR_TEAM_NAME = 'collaborator'
+export const COLLABORATOR_TEAM_ID = process.env.NEXT_PUBLIC_APPWRITE_COLLABORATOR_TEAM_ID ?? COLLABORATOR_TEAM_NAME
+
+const ensureRoleExists = (roleId: string, roleName: string): (() => Promise) => {
+ let roleExists = false
+ return async (): Promise => {
+ if (roleExists) return
+ try {
+ await teams.get(roleId)
+ roleExists = true
+ } catch (error) {
+ await teams.create(roleId, roleName)
+ roleExists = true
+ }
+ }
+}
+
+export const ensureRoles = async (): Promise => {
+ const adminRole = ensureRoleExists(ADMIN_TEAM_ID, ADMIN_TEAM_NAME)
+ const moderatorRole = ensureRoleExists(MODERATOR_TEAM_ID, MODERATOR_TEAM_NAME)
+ const collaboratorRole = ensureRoleExists(COLLABORATOR_TEAM_ID, COLLABORATOR_TEAM_NAME)
+
+ await Promise.all([
+ adminRole(),
+ moderatorRole(),
+ collaboratorRole()
+ ])
+}
diff --git a/src/services/backend/teamApply.ts b/src/services/backend/teamApply.ts
new file mode 100644
index 0000000..bedfd68
--- /dev/null
+++ b/src/services/backend/teamApply.ts
@@ -0,0 +1,32 @@
+import { Permission, Role, databases } from '@/lib/nodeAppwrite'
+import { DATABASE_ID, ensureDatabase } from '@/services/backend/database'
+import { ADMIN_TEAM_ID } from './roles'
+
+export const TEAM_APPLY_COLLECTION_NAME = 'team-apply'
+export const TEAM_APPLY_COLLECTION_ID = process.env.NEXT_PUBLIC_APPWRITE_TEAM_APPLY_COLLECTION_ID ?? TEAM_APPLY_COLLECTION_NAME
+
+export const ensureTeamApplyCollection = (() => {
+ let collectionEnsured = false
+ return async () => {
+ if (collectionEnsured) return
+ await ensureDatabase()
+ try {
+ await databases.getCollection(DATABASE_ID, TEAM_APPLY_COLLECTION_ID)
+ } catch (error) {
+ const permissions = [
+ Permission.create(Role.any()),
+ Permission.read(Role.team(ADMIN_TEAM_ID)),
+ Permission.update(Role.team(ADMIN_TEAM_ID)),
+ Permission.delete(Role.team(ADMIN_TEAM_ID))
+ ]
+ await databases.createCollection(DATABASE_ID, TEAM_APPLY_COLLECTION_ID, TEAM_APPLY_COLLECTION_NAME, permissions, false, true)
+ await databases.createStringAttribute(DATABASE_ID, TEAM_APPLY_COLLECTION_ID, 'name', 128, true)
+ await databases.createEmailAttribute(DATABASE_ID, TEAM_APPLY_COLLECTION_ID, 'email', true)
+ await databases.createStringAttribute(DATABASE_ID, TEAM_APPLY_COLLECTION_ID, 'discordName', 128, true)
+ await databases.createStringAttribute(DATABASE_ID, TEAM_APPLY_COLLECTION_ID, 'role', 24, true)
+ await databases.createStringAttribute(DATABASE_ID, TEAM_APPLY_COLLECTION_ID, 'message', 4096, true)
+ } finally {
+ collectionEnsured = true
+ }
+ }
+})()
diff --git a/src/services/frontend/database.ts b/src/services/frontend/database.ts
new file mode 100644
index 0000000..2257640
--- /dev/null
+++ b/src/services/frontend/database.ts
@@ -0,0 +1,2 @@
+export const DATABASE_NAME = 'entgamers-website'
+export const DATABASE_ID = process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID ?? DATABASE_NAME
diff --git a/src/services/frontend/teamApply.ts b/src/services/frontend/teamApply.ts
new file mode 100644
index 0000000..ded76a4
--- /dev/null
+++ b/src/services/frontend/teamApply.ts
@@ -0,0 +1,25 @@
+import { ID, databases } from '@/lib/appwrite'
+import { DATABASE_ID } from '@/services/frontend/database'
+import { type TeamApplyData, type TeamApplyDocument, type TeamApplyList } from '@/types/teamApply'
+
+export const TEAM_APPLY_COLLECTION_NAME = 'team-apply'
+export const TEAM_APPLY_COLLECTION_ID = process.env.NEXT_PUBLIC_APPWRITE_TEAM_APPLY_COLLECTION_ID ?? TEAM_APPLY_COLLECTION_NAME
+
+export const createTeamApply = async (data: TeamApplyData): Promise => {
+ const createdTeamApply = await databases.createDocument(DATABASE_ID, TEAM_APPLY_COLLECTION_ID, ID.unique(), data)
+ return createdTeamApply
+}
+
+export const getTeamApply = async (teamApplyId: string): Promise => {
+ const teamApply = await databases.getDocument(DATABASE_ID, TEAM_APPLY_COLLECTION_ID, teamApplyId)
+ return teamApply
+}
+
+export const listTeamApply = async (): Promise => {
+ const teamApplyList = await databases.listDocuments(DATABASE_ID, TEAM_APPLY_COLLECTION_ID)
+ return teamApplyList
+}
+
+export const deleteTeamApply = async (teamApplyId: string): Promise => {
+ await databases.deleteDocument(DATABASE_ID, TEAM_APPLY_COLLECTION_ID, teamApplyId)
+}
diff --git a/src/types/User.ts b/src/types/User.ts
index 40ec753..6584154 100644
--- a/src/types/User.ts
+++ b/src/types/User.ts
@@ -1,5 +1,7 @@
import { type IconDefinition } from '@fortawesome/fontawesome-svg-core'
+export type UserPreferences = Record
+
export interface TeamMember {
image: string
name: string
diff --git a/src/types/teamApply.ts b/src/types/teamApply.ts
new file mode 100644
index 0000000..bb50058
--- /dev/null
+++ b/src/types/teamApply.ts
@@ -0,0 +1,13 @@
+import { type Models } from 'appwrite'
+
+export interface TeamApplyData {
+ name: string
+ email: string
+ discordName: string
+ message: string
+ role: 'moderator' | 'administrator' | 'collaborator'
+}
+
+export type TeamApplyDocument = Models.Document & TeamApplyData
+
+export type TeamApplyList = Models.DocumentList
diff --git a/yarn.lock b/yarn.lock
index bd6416b..9ab4c6f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3325,6 +3325,16 @@ __metadata:
languageName: node
linkType: hard
+"appwrite@npm:^13.0.0":
+ version: 13.0.0
+ resolution: "appwrite@npm:13.0.0"
+ dependencies:
+ cross-fetch: 3.1.5
+ isomorphic-form-data: 2.0.0
+ checksum: 0495fef9e4b62c8c1317bedf28d7d6f5ac713536bf0a155386356f23161d59b82f3529116c5374d0a914215974f5bf48a0c5728b7b98397eb9c0693cf29e7a23
+ languageName: node
+ linkType: hard
+
"aproba@npm:^1.0.3 || ^2.0.0":
version: 2.0.0
resolution: "aproba@npm:2.0.0"
@@ -3579,6 +3589,13 @@ __metadata:
languageName: node
linkType: hard
+"asynckit@npm:^0.4.0":
+ version: 0.4.0
+ resolution: "asynckit@npm:0.4.0"
+ checksum: 7b78c451df768adba04e2d02e63e2d0bf3b07adcd6e42b4cf665cb7ce899bedd344c69a1dcbce355b5f972d597b25aaa1c1742b52cffd9caccb22f348114f6be
+ languageName: node
+ linkType: hard
+
"autoprefixer@npm:10.4.15":
version: 10.4.15
resolution: "autoprefixer@npm:10.4.15"
@@ -3611,6 +3628,17 @@ __metadata:
languageName: node
linkType: hard
+"axios@npm:^1.4.0":
+ version: 1.5.0
+ resolution: "axios@npm:1.5.0"
+ dependencies:
+ follow-redirects: ^1.15.0
+ form-data: ^4.0.0
+ proxy-from-env: ^1.1.0
+ checksum: e7405a5dbbea97760d0e6cd58fecba311b0401ddb4a8efbc4108f5537da9b3f278bde566deb777935a960beec4fa18e7b8353881f2f465e4f2c0e949fead35be
+ languageName: node
+ linkType: hard
+
"axobject-query@npm:^3.1.1":
version: 3.2.1
resolution: "axobject-query@npm:3.2.1"
@@ -4115,6 +4143,15 @@ __metadata:
languageName: node
linkType: hard
+"combined-stream@npm:^1.0.6, combined-stream@npm:^1.0.8":
+ version: 1.0.8
+ resolution: "combined-stream@npm:1.0.8"
+ dependencies:
+ delayed-stream: ~1.0.0
+ checksum: 49fa4aeb4916567e33ea81d088f6584749fc90c7abec76fd516bf1c5aa5c79f3584b5ba3de6b86d26ddd64bae5329c4c7479343250cfe71c75bb366eae53bb7c
+ languageName: node
+ linkType: hard
+
"comma-separated-tokens@npm:^2.0.0":
version: 2.0.3
resolution: "comma-separated-tokens@npm:2.0.3"
@@ -4235,6 +4272,15 @@ __metadata:
languageName: node
linkType: hard
+"cross-fetch@npm:3.1.5":
+ version: 3.1.5
+ resolution: "cross-fetch@npm:3.1.5"
+ dependencies:
+ node-fetch: 2.6.7
+ checksum: f6b8c6ee3ef993ace6277fd789c71b6acf1b504fd5f5c7128df4ef2f125a429e29cd62dc8c127523f04a5f2fa4771ed80e3f3d9695617f441425045f505cf3bb
+ languageName: node
+ linkType: hard
+
"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3":
version: 7.0.3
resolution: "cross-spawn@npm:7.0.3"
@@ -4438,6 +4484,13 @@ __metadata:
languageName: node
linkType: hard
+"delayed-stream@npm:~1.0.0":
+ version: 1.0.0
+ resolution: "delayed-stream@npm:1.0.0"
+ checksum: 46fe6e83e2cb1d85ba50bd52803c68be9bd953282fa7096f51fc29edd5d67ff84ff753c51966061e5ba7cb5e47ef6d36a91924eddb7f3f3483b1c560f77a0020
+ languageName: node
+ linkType: hard
+
"delegates@npm:^1.0.0":
version: 1.0.0
resolution: "delegates@npm:1.0.0"
@@ -5542,6 +5595,16 @@ __metadata:
languageName: node
linkType: hard
+"follow-redirects@npm:^1.15.0":
+ version: 1.15.3
+ resolution: "follow-redirects@npm:1.15.3"
+ peerDependenciesMeta:
+ debug:
+ optional: true
+ checksum: 584da22ec5420c837bd096559ebfb8fe69d82512d5585004e36a3b4a6ef6d5905780e0c74508c7b72f907d1fa2b7bd339e613859e9c304d0dc96af2027fd0231
+ languageName: node
+ linkType: hard
+
"for-each@npm:^0.3.3":
version: 0.3.3
resolution: "for-each@npm:0.3.3"
@@ -5561,6 +5624,28 @@ __metadata:
languageName: node
linkType: hard
+"form-data@npm:^2.3.2":
+ version: 2.5.1
+ resolution: "form-data@npm:2.5.1"
+ dependencies:
+ asynckit: ^0.4.0
+ combined-stream: ^1.0.6
+ mime-types: ^2.1.12
+ checksum: 5134ada56cc246b293a1ac7678dba6830000603a3979cf83ff7b2f21f2e3725202237cfb89e32bcb38a1d35727efbd3c3a22e65b42321e8ade8eec01ce755d08
+ languageName: node
+ linkType: hard
+
+"form-data@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "form-data@npm:4.0.0"
+ dependencies:
+ asynckit: ^0.4.0
+ combined-stream: ^1.0.8
+ mime-types: ^2.1.12
+ checksum: 01135bf8675f9d5c61ff18e2e2932f719ca4de964e3be90ef4c36aacfc7b9cb2fceb5eca0b7e0190e3383fe51c5b37f4cb80b62ca06a99aaabfcfd6ac7c9328c
+ languageName: node
+ linkType: hard
+
"formik@npm:^2.4.4":
version: 2.4.4
resolution: "formik@npm:2.4.4"
@@ -6729,6 +6814,15 @@ __metadata:
languageName: node
linkType: hard
+"isomorphic-form-data@npm:2.0.0":
+ version: 2.0.0
+ resolution: "isomorphic-form-data@npm:2.0.0"
+ dependencies:
+ form-data: ^2.3.2
+ checksum: 234bfaa1ed037b1d6cf659eb7a5806889f1f60bc4c7effe5f54e52506004604a9d7229a03a8f9656a1a7ea5fcedca4342277083e38f88ff910b64eefa97dd95e
+ languageName: node
+ linkType: hard
+
"iterator.prototype@npm:^1.1.2":
version: 1.1.2
resolution: "iterator.prototype@npm:1.1.2"
@@ -7790,6 +7884,22 @@ __metadata:
languageName: node
linkType: hard
+"mime-db@npm:1.52.0":
+ version: 1.52.0
+ resolution: "mime-db@npm:1.52.0"
+ checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f
+ languageName: node
+ linkType: hard
+
+"mime-types@npm:^2.1.12":
+ version: 2.1.35
+ resolution: "mime-types@npm:2.1.35"
+ dependencies:
+ mime-db: 1.52.0
+ checksum: 89a5b7f1def9f3af5dad6496c5ed50191ae4331cc5389d7c521c8ad28d5fdad2d06fd81baf38fed813dc4e46bb55c8145bb0ff406330818c9cf712fb2e9b3836
+ languageName: node
+ linkType: hard
+
"mime@npm:^3.0.0":
version: 3.0.0
resolution: "mime@npm:3.0.0"
@@ -8082,6 +8192,7 @@ __metadata:
"@types/react-dom": ^18.2.7
"@typescript-eslint/eslint-plugin": ^6.4.0
"@typescript-eslint/parser": ^5.38.0
+ appwrite: ^13.0.0
entgamers-panda-preset: 0.0.7
eslint: ^8.0.1
eslint-config-next: latest
@@ -8099,6 +8210,7 @@ __metadata:
isomorphic-fetch: ^3.0.0
next: 13.4.19
next-connect: ^1.0.0
+ node-appwrite: ^11.0.0
react: 18.2.0
react-dom: 18.2.0
sharp: ^0.32.5
@@ -8190,6 +8302,16 @@ __metadata:
languageName: node
linkType: hard
+"node-appwrite@npm:^11.0.0":
+ version: 11.0.0
+ resolution: "node-appwrite@npm:11.0.0"
+ dependencies:
+ axios: ^1.4.0
+ form-data: ^4.0.0
+ checksum: ccbfe4ba7bab28a964d22018a7c38c8ad2c8447dc8f4bb310ed3d127aecf373fffc4e53ef8a5162f91dfa84b1e7eae5c160d2e4fee2c598a848131636e39e5fd
+ languageName: node
+ linkType: hard
+
"node-eval@npm:^2.0.0":
version: 2.0.0
resolution: "node-eval@npm:2.0.0"
@@ -8199,6 +8321,20 @@ __metadata:
languageName: node
linkType: hard
+"node-fetch@npm:2.6.7":
+ version: 2.6.7
+ resolution: "node-fetch@npm:2.6.7"
+ dependencies:
+ whatwg-url: ^5.0.0
+ peerDependencies:
+ encoding: ^0.1.0
+ peerDependenciesMeta:
+ encoding:
+ optional: true
+ checksum: 8d816ffd1ee22cab8301c7756ef04f3437f18dace86a1dae22cf81db8ef29c0bf6655f3215cb0cdb22b420b6fe141e64b26905e7f33f9377a7fa59135ea3e10b
+ languageName: node
+ linkType: hard
+
"node-fetch@npm:^2.6.1":
version: 2.7.0
resolution: "node-fetch@npm:2.7.0"
@@ -8956,6 +9092,13 @@ __metadata:
languageName: node
linkType: hard
+"proxy-from-env@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "proxy-from-env@npm:1.1.0"
+ checksum: ed7fcc2ba0a33404958e34d95d18638249a68c430e30fcb6c478497d72739ba64ce9810a24f53a7d921d0c065e5b78e3822759800698167256b04659366ca4d4
+ languageName: node
+ linkType: hard
+
"pump@npm:^3.0.0":
version: 3.0.0
resolution: "pump@npm:3.0.0"