chore: upgrade next and deps

This commit is contained in:
2026-04-01 13:46:02 -06:00
parent f8018048bc
commit 57a6032a24
48 changed files with 488 additions and 390 deletions
-1
View File
@@ -1 +0,0 @@
src/styled-system
-55
View File
@@ -1,55 +0,0 @@
{
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"next/core-web-vitals",
"standard-with-typescript",
"plugin:react/recommended"
],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"react/react-in-jsx-scope": "off",
"react/jsx-uses-react": "off",
"indent": "off",
"@typescript-eslint/indent": [
"error",
2,
{
"SwitchCase": 1
}
],
"react/jsx-indent": [
"error",
2
],
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": [
"error"
],
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_"
}
],
"react-hooks/exhaustive-deps": "off",
"react/no-unknown-property": [
"error",
{
"ignore": [
"css"
]
}
]
}
}
BIN
View File
Binary file not shown.
+12 -12
View File
@@ -19,13 +19,13 @@ module.exports = {
deploy: {
production: {
user: process.env.SSH_USERNAME,
host: process.env.DEPLOY_HOST,
ref: 'origin/production',
repo: 'https://github.com/SrJuggernaut/entgamers_pro',
path: process.env.DEPLOY_PATH,
'user': process.env.SSH_USERNAME,
'host': process.env.DEPLOY_HOST,
'ref': 'origin/production',
'repo': 'https://github.com/SrJuggernaut/entgamers_pro',
'path': process.env.DEPLOY_PATH,
'post-deploy': 'pm2 --silent startOrRestart ecosystem.config.js',
env: {
'env': {
PORT: process.env.PORT,
NEXT_PUBLIC_APPWRITE_ENDPOINT: process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT,
NEXT_PUBLIC_APPWRITE_PROJECT_ID: process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID,
@@ -37,13 +37,13 @@ module.exports = {
},
preview: {
user: process.env.SSH_USERNAME,
host: process.env.DEPLOY_HOST,
ref: 'origin/preview',
repo: 'https://github.com/SrJuggernaut/entgamers_pro',
path: process.env.DEPLOY_PATH,
'user': process.env.SSH_USERNAME,
'host': process.env.DEPLOY_HOST,
'ref': 'origin/preview',
'repo': 'https://github.com/SrJuggernaut/entgamers_pro',
'path': process.env.DEPLOY_PATH,
'post-deploy': 'pm2 --silent startOrRestart ecosystem.config.js',
env: {
'env': {
PORT: process.env.PORT,
NEXT_PUBLIC_APPWRITE_ENDPOINT: process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT,
NEXT_PUBLIC_APPWRITE_PROJECT_ID: process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID,
+98
View File
@@ -0,0 +1,98 @@
import eslintJs from '@eslint/js'
import nextPlugin from '@next/eslint-plugin-next'
import jsxA11yPlugin from 'eslint-plugin-jsx-a11y'
import reactPlugin from 'eslint-plugin-react'
import reactHooksPlugin from 'eslint-plugin-react-hooks'
import { defineConfig, globalIgnores } from 'eslint/config'
import globals from 'globals'
import tseslint from 'typescript-eslint'
import stylisticPlugin from '@stylistic/eslint-plugin'
export default defineConfig([
globalIgnores([
'node_modules/',
'public/', 'src/styled-system/**/*', '.next/**',
'out/**',
'build/**',
'next-env.d.ts']),
{
name: 'entgamers_pro/globals',
languageOptions: {
globals: {
...globals.browser,
...globals.node
}
}
},
{
name: 'project/eslint-js',
files: ['**/*.{js,mjs,ts,tsx}'],
...eslintJs.configs.recommended
},
{
name: 'project/typescript',
files: ['**/*.{ts,tsx}'],
extends: [
...tseslint.configs.recommended
],
rules: {
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }]
}
},
{
name: 'project/react-next',
files: ['**/*.{jsx,tsx}'],
plugins: {
'react': reactPlugin,
'react-hooks': reactHooksPlugin,
'jsx-a11y': jsxA11yPlugin,
'@next/next': nextPlugin
},
rules: {
...reactPlugin.configs.recommended.rules,
...reactPlugin.configs['jsx-runtime'].rules,
...reactHooksPlugin.configs['recommended-latest'].rules,
...jsxA11yPlugin.configs.strict.rules,
...nextPlugin.configs.recommended.rules,
...nextPlugin.configs['core-web-vitals'].rules,
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
'react/no-unknown-property': 'off',
'react/jsx-no-target-blank': 'off',
'jsx-a11y/alt-text': ['warn', { elements: ['img'], img: ['Image'] }],
'jsx-a11y/media-has-caption': 'warn'
},
settings: {
react: {
version: '19'
}
}
},
{
name: 'project/stylistic',
files: ['**/*.{js,mjs,ts,tsx}'],
plugins: {
'@stylistic': stylisticPlugin
},
rules: {
// Remove legacy formatting rules from ESLint core
...stylisticPlugin.configs['disable-legacy'].rules,
// Add recommended stylistic rules
...stylisticPlugin.configs.recommended.rules,
'@stylistic/indent': ['warn', 2],
'@stylistic/quotes': ['warn', 'single', {
avoidEscape: true,
allowTemplateLiterals: 'always'
}],
'@stylistic/semi': ['warn', 'never'],
'@stylistic/comma-dangle': ['warn', 'never'],
'@stylistic/arrow-parens': ['warn', 'always', {
requireForBlockBody: true
}],
'@stylistic/brace-style': ['warn', '1tbs', {
allowSingleLine: true
}]
}
}
])
+2 -1
View File
@@ -1,5 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
+1 -1
View File
@@ -1,4 +1,4 @@
const imageDomains = (process.env.IMAGE_DOMAINS ?? '').split(',').map(domain => {
const imageDomains = (process.env.IMAGE_DOMAINS ?? '').split(',').map((domain) => {
const getDataRegex = /(?<protocol>[\w]+)?:\/\/(?<hostname>[\w.-]+)?((?<=[\d]{0,4}):(?<port>[\d]{0,4}))?\/?(?<pathname>.*)?$/
const groups = getDataRegex.exec(domain).groups ?? {}
return groups
+15 -20
View File
@@ -7,7 +7,7 @@
"build": "next build",
"prestart": "bun install && next build",
"start": "next start",
"lint": "next lint",
"lint": "eslint .",
"prepare": "panda codegen && husky install"
},
"dependencies": {
@@ -18,6 +18,7 @@
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@reduxjs/toolkit": "^2.0.1",
"@stylistic/eslint-plugin": "^5.10.0",
"@tanstack/match-sorter-utils": "^8.11.8",
"@tanstack/react-table": "^8.19.3",
"appwrite": "^13.0.1",
@@ -25,12 +26,12 @@
"entgamers-database": "0.0.26",
"entgamers-panda-preset": "0.1.5",
"formik": "^2.4.5",
"framer-motion": "^10.17.6",
"framer-motion": "^12.38.0",
"isomorphic-fetch": "^3.0.0",
"next": "^14.0.4",
"next": "16.2.2",
"node-appwrite": "^11.1.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"react-redux": "^9.0.4",
"sharp": "^0.33.1",
"yup": "^1.3.3"
@@ -38,23 +39,17 @@
"devDependencies": {
"@commitlint/cli": "^18.4.4",
"@commitlint/config-conventional": "^18.4.4",
"@eslint/js": "^10.0.1",
"@pandacss/dev": "^0.23.0",
"@types/isomorphic-fetch": "^0.0.39",
"@types/node": "^20.10.6",
"@types/react": "^18.2.46",
"@types/react-dom": "^18.2.18",
"@typescript-eslint/eslint-plugin": "^6.4.0",
"@typescript-eslint/parser": "^5.38.0",
"eslint": "^8.0.1",
"eslint-config-next": "latest",
"eslint-config-standard": "^17.0.0",
"eslint-config-standard-with-typescript": "latest",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-n": "^15.0.0 || ^16.0.0 ",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "latest",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"eslint": "^10.1.0",
"eslint-config-next": "16.2.2",
"eslint-plugin-react": "^7.37.5",
"husky": "^8.0.3",
"typescript": "*"
"typescript": "*",
"typescript-eslint": "^8.58.0"
}
}
}
+1 -1
View File
@@ -22,7 +22,7 @@ const Clanes: FC = () => {
<div
className={card({ variant: 'glass' }).content}
>
<Typography variant="h2" align='center'>Clanes</Typography>
<Typography variant="h2" align="center">Clanes</Typography>
<div
className={css({
display: 'grid',
+2 -2
View File
@@ -13,7 +13,7 @@ import { type FC } from 'react'
import { createPortal } from 'react-dom'
const FeedbackConsumer: FC = () => {
const { alerts } = useAppSelector(state => state.feedback)
const { alerts } = useAppSelector((state) => state.feedback)
const dispatch = useAppDispatch()
return (
<>
@@ -55,7 +55,7 @@ const FeedbackConsumer: FC = () => {
className={alert().closeButton}
onClick={() => dispatch(removeAlert(currentAlert.id))}
>
<FontAwesomeIcon icon={faTimes} fixedWidth size='sm'/>
<FontAwesomeIcon icon={faTimes} fixedWidth size="sm" />
</IconButton>
<Typography variant="h3" component="div">
{currentAlert.title}
+9 -9
View File
@@ -111,20 +111,20 @@ const Hero: FC = () => {
color: 'primary',
size: 'large'
}), css({
position: 'absolute',
bottom: '45px',
right: '50%',
animationName: 'bounce',
animationDuration: '1s',
animationIterationCount: 'infinite',
transform: 'translateX(50%)',
zIndex: 1,
'position': 'absolute',
'bottom': '45px',
'right': '50%',
'animationName': 'bounce',
'animationDuration': '1s',
'animationIterationCount': 'infinite',
'transform': 'translateX(50%)',
'zIndex': 1,
'&:hover': {
animationPlayState: 'paused'
}
}))}
>
<FontAwesomeIcon icon={faArrowDown} size='lg' fixedWidth />
<FontAwesomeIcon icon={faArrowDown} size="lg" fixedWidth />
</a>
</section>
)
+6 -11
View File
@@ -5,15 +5,14 @@ import { setClanes, setCurrentUser, setSession, setStatus } from '@/state/sessio
import { AppwriteException } from 'appwrite'
import { getClanes } from 'entgamers-database/frontend/clanes'
import { getCurrentUser, getSession } from 'entgamers-database/frontend/session'
import { useCallback, useEffect, type FC } from 'react'
import { useCallback, useEffect } from 'react'
const SessionConsumer: FC = () => {
const SessionConsumer = () => {
const { status, session, user, clanes } = useAppSelector((state) => state.session)
const dispatch = useAppDispatch()
const ensureSession = useCallback(async () => {
try {
if (status !== 'initializing' || session !== undefined) return
dispatch(setStatus('loading'))
const currentSession = await getSession('current')
const currentUser = await getCurrentUser()
@@ -26,16 +25,17 @@ const SessionConsumer: FC = () => {
} finally {
dispatch(setStatus('idle'))
}
}, [])
}, [dispatch])
useEffect(() => {
if (status !== 'initializing' || session !== undefined) return
ensureSession()
.catch((error) => {
if (error instanceof AppwriteException) {
console.error(error)
}
})
}, [])
}, [status, session, ensureSession])
useEffect(() => {
if (user !== undefined && clanes === undefined) {
@@ -51,11 +51,6 @@ const SessionConsumer: FC = () => {
} else if (user === undefined && clanes !== undefined) {
dispatch(setClanes())
}
}, [user])
return (
<>
</>
)
}, [user, clanes, dispatch])
}
export default SessionConsumer
+1 -1
View File
@@ -52,7 +52,7 @@ const Social: FC = () => {
<div
className={card({ variant: 'glass' }).content}
>
<Typography variant="h2" align='center'>Redes Sociales</Typography>
<Typography variant="h2" align="center">Redes Sociales</Typography>
<Typography variant="body1">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptate deleniti dolore quas sed nemo sit, officia in rem nesciunt quisquam possimus ab! Labore sed reprehenderit quae, hic earum tempora placeat cumque id eos itaque perferendis nulla officia fuga porro, quis, unde facere accusamus repudiandae non?
</Typography>
+44 -13
View File
@@ -21,37 +21,68 @@ const ClanesPage: FC = () => {
<Typography variant="h2">Beneficios de los clanes</Typography>
<Typography variant="body1">La intención de EntGamers es brindar beneficios a los clanes que les permitan operar en un ambiente de comunicación y colaboración.</Typography>
<ul className="fa-ul">
<li><FontAwesomeIcon icon={faChevronRight} listItem /> Espacio en el servidor de Discord.</li>
<li><FontAwesomeIcon icon={faChevronRight} listItem /> Apoyo de la administración con proyectos y eventos.</li>
<li><FontAwesomeIcon icon={faChevronRight} listItem /> Apoyo del equipo de moderación.</li>
<li>
<FontAwesomeIcon icon={faChevronRight} listItem />
{' '}
Espacio en el servidor de Discord.
</li>
<li>
<FontAwesomeIcon icon={faChevronRight} listItem />
{' '}
Apoyo de la administración con proyectos y eventos.
</li>
<li>
<FontAwesomeIcon icon={faChevronRight} listItem />
{' '}
Apoyo del equipo de moderación.
</li>
</ul>
</div>
<div>
<Typography variant="h2">Requisitos para formar un clan</Typography>
<Typography variant="body1">Todos los clanes deben cumplir con los siguientes requisitos:</Typography>
<ul className="fa-ul">
<li><FontAwesomeIcon icon={faChevronRight} listItem /> Tener un encargado.</li>
<li><FontAwesomeIcon icon={faChevronRight} listItem /> Fomentar el compañerismo y la comunidad.</li>
<li><FontAwesomeIcon icon={faChevronRight} listItem /> Aportar contenido de forma periódica para la comunidad.</li>
<li><FontAwesomeIcon icon={faChevronRight} listItem /> Realizar al menos una actividad mensual con los integrantes.</li>
<li>
<FontAwesomeIcon icon={faChevronRight} listItem />
{' '}
Tener un encargado.
</li>
<li>
<FontAwesomeIcon icon={faChevronRight} listItem />
{' '}
Fomentar el compañerismo y la comunidad.
</li>
<li>
<FontAwesomeIcon icon={faChevronRight} listItem />
{' '}
Aportar contenido de forma periódica para la comunidad.
</li>
<li>
<FontAwesomeIcon icon={faChevronRight} listItem />
{' '}
Realizar al menos una actividad mensual con los integrantes.
</li>
</ul>
</div>
</div>
<Typography variant="h2">Clanes activos</Typography>
<div
className={css({
backgroundColor: 'info',
color: 'info.contrast',
borderRadius: 'medium',
padding: 'medium',
marginBlock: 'medium',
'backgroundColor': 'info',
'color': 'info.contrast',
'borderRadius': 'medium',
'padding': 'medium',
'marginBlock': 'medium',
'& a': {
color: 'info.contrast',
fontWeight: 'bold'
}
})}
>
Esta sección está en construcción. Puedes ver los clanes activos en nuestro <a href="http://discord.gg/nqwzHJC">Servidor de Discord</a>.
Esta sección está en construcción. Puedes ver los clanes activos en nuestro
{' '}
<a href="http://discord.gg/nqwzHJC">Servidor de Discord</a>
.
</div>
</Container>
)
+5 -3
View File
@@ -44,7 +44,7 @@ const CuentaTabs: FC = () => {
>
<AnimatePresence
initial={false}
mode='wait'
mode="wait"
>
{currentTab === 'login' && (
<motion.div
@@ -52,7 +52,8 @@ const CuentaTabs: FC = () => {
initial={{ opacity: 0, x: '-100%' }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: '100%' }}
key="login">
key="login"
>
<UpdateEmail />
<UpdatePassword />
</motion.div>
@@ -63,7 +64,8 @@ const CuentaTabs: FC = () => {
initial={{ opacity: 0, x: '-100%' }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: '100%' }}
key="perfil">
key="perfil"
>
<UpdateUserName />
<UpdateUserPreferences />
</motion.div>
+2 -3
View File
@@ -68,7 +68,7 @@ const UpdateUserName: FC = () => {
})
.catch(console.error)
}
}, [status, session, user])
}, [status, session, user, formik])
if (status !== 'idle' || session === undefined) {
// TODO: Replace with Skeleton
@@ -99,8 +99,7 @@ const UpdateUserName: FC = () => {
<Typography variant="caption" color="danger">{formik.errors.name}</Typography>
)}
</FormGroup>
<FormGroup
>
<FormGroup>
<Button
type="submit"
disabled={formik.isSubmitting || !formik.isValid}
+6 -6
View File
@@ -55,7 +55,7 @@ const UpdateUserPreferences: FC = () => {
})
.catch(console.error)
}
}, [status, session])
}, [status, user, formik, session])
if (status !== 'idle' || session === undefined) {
// TODO: Replace with Skeleton
@@ -65,7 +65,7 @@ const UpdateUserPreferences: FC = () => {
return (
<>
<Typography
variant='h3'
variant="h3"
>
Preferencias
</Typography>
@@ -74,13 +74,13 @@ const UpdateUserPreferences: FC = () => {
>
<FormGroup>
<label
htmlFor='bio'
htmlFor="bio"
>
Biografia
</label>
<TextArea
id='bio'
name='bio'
id="bio"
name="bio"
value={formik.values.bio}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
@@ -96,7 +96,7 @@ const UpdateUserPreferences: FC = () => {
{/* TODO: Add Profile Picture and Social Links fields */}
<FormGroup>
<Button
type='submit'
type="submit"
disabled={formik.isSubmitting || !formik.isValid}
fullWidth
>
+2 -2
View File
@@ -1,6 +1,6 @@
import Typography from '@/components/ui/Typography'
import { Container } from '@/styled-system/jsx'
import { type FC } from 'react'
import type { FC } from 'react'
import CuentaTabs from './CuentaTabs'
const CuentaPage: FC = () => {
@@ -10,7 +10,7 @@ const CuentaPage: FC = () => {
<Typography variant="body1">
Desde aquí puedes administrar las preferencias y ajustes de tu cuenta.
</Typography>
<CuentaTabs/>
<CuentaTabs />
</Container>
)
}
@@ -40,7 +40,7 @@ const DashboardTabs: FC = () => {
>
<AnimatePresence
initial={false}
mode='wait'
mode="wait"
>
{currentTab === undefined && (
<motion.div
@@ -17,7 +17,7 @@ const ApplicationsFilter: FC<ApplicationsFilterProps> = ({ column }) => {
<StatusSelector
id={`${column.id}-status-filter`}
value={columnFilterValue as TeamApplicationStatus}
onChange={value => { column.setFilterValue(value) }}
onChange={(value) => { column.setFilterValue(value) }}
allowEmpty
/>
)
@@ -26,7 +26,7 @@ const ApplicationsFilter: FC<ApplicationsFilterProps> = ({ column }) => {
<RoleSelector
id={`${column.id}-role-filter`}
value={columnFilterValue as TeamApplicationRole}
onChange={value => { column.setFilterValue(value) }}
onChange={(value) => { column.setFilterValue(value) }}
allowEmpty
/>
)
@@ -36,7 +36,7 @@ const ApplicationsFilter: FC<ApplicationsFilterProps> = ({ column }) => {
fullWidth
type="text"
value={(columnFilterValue ?? '') as string}
onChange={value => { column.setFilterValue(value) }}
onChange={(value) => { column.setFilterValue(value) }}
placeholder="Buscar..."
className="w-36 border shadow rounded"
list={column.id + 'list'}
@@ -3,7 +3,7 @@ import { Table, TableBody, TableCell, TableContainer, TableHead, TableHeadCell,
import useManageError from '@/hooks/useManageError'
import { css } from '@/styled-system/css'
import { formatDate } from '@/utilities/date'
import { type TeamApplication, type TeamApplicationList } from '@/utilities/teamApplication'
import type { TeamApplication, TeamApplicationList } from '@/utilities/teamApplication'
import { faChevronLeft, faChevronRight, faSort, faSortAsc, faSortDesc } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { createColumnHelper, flexRender, getCoreRowModel, useReactTable, type ColumnFiltersState, type PaginationState, type RowData, type SortingState } from '@tanstack/react-table'
@@ -29,7 +29,7 @@ const columns = [
columnHelper.accessor('status', {
header: 'Estado',
cell: StatusUpdater,
getUniqueValues () {
getUniqueValues() {
return ['Pending', 'Accepted', 'Rejected']
}
}),
@@ -125,7 +125,7 @@ const ApplicationsList: FC = () => {
if (error instanceof Error && error.name === 'AbortError') return
manageError(error, 'Error al obtener las aplicaciones', 'Error desconocido al obtener las aplicaciones', 'error')
})
}, [pagination, sorting, columnFilters])
}, [pagination, sorting, columnFilters, manageError])
// TODO: Better UI Controls for: column visibility. Quantity selector.
return (
@@ -145,7 +145,9 @@ const ApplicationsList: FC = () => {
id={`${column.id}-view`}
checked={column.getIsVisible()}
onChange={column.getToggleVisibilityHandler()}
/> {column.columnDef.header?.toString() ?? column.id}
/>
{' '}
{column.columnDef.header?.toString() ?? column.id}
</label>
</div>
))}
@@ -159,8 +161,8 @@ const ApplicationsList: FC = () => {
<TableHeadCell
key={header.id}
className={css({
verticalAlign: 'top',
position: 'relative',
'verticalAlign': 'top',
'position': 'relative',
'&:hover > [data-is-resizing]': {
backgroundColor: 'border'
}
@@ -193,21 +195,21 @@ const ApplicationsList: FC = () => {
</div>
{header.column.getCanFilter()
? (
<ApplicationsFilter column={header.column}/>
<ApplicationsFilter column={header.column} />
)
: null
}
: null}
</div>
<div
<button
type="button"
className={css({
position: 'absolute',
top: 0,
right: 0,
height: '100%',
width: '5px',
cursor: 'col-resize',
userSelect: 'none',
touchAction: 'none',
'position': 'absolute',
'top': 0,
'right': 0,
'height': '100%',
'width': '5px',
'cursor': 'col-resize',
'userSelect': 'none',
'touchAction': 'none',
'&:hover': {
backgroundColor: 'border'
},
@@ -257,7 +259,13 @@ const ApplicationsList: FC = () => {
>
<FontAwesomeIcon icon={faChevronLeft} fixedWidth />
</IconButton>
Pagina {table.getState().pagination.pageIndex + 1} de {table.getPageCount()}
Pagina
{' '}
{table.getState().pagination.pageIndex + 1}
{' '}
de
{' '}
{table.getPageCount()}
<IconButton
onClick={() => { table.nextPage() }}
disabled={!table.getCanNextPage()}
@@ -15,17 +15,17 @@ const RoleSelector: FC<RoleSelectorProps> = ({ id, value, onChange, allowEmpty }
<select
id={`${id}-status`}
className={css({
width: '100%',
border: 'none',
background: 'transparent',
color: 'inherit',
outline: 'none',
cursor: 'pointer',
fontSize: 'inherit',
fontWeight: 'inherit',
lineHeight: 'inherit',
padding: '0',
borderRadius: '0',
'width': '100%',
'border': 'none',
'background': 'transparent',
'color': 'inherit',
'outline': 'none',
'cursor': 'pointer',
'fontSize': 'inherit',
'fontWeight': 'inherit',
'lineHeight': 'inherit',
'padding': '0',
'borderRadius': '0',
'&:focus': {
outline: 'none'
}
@@ -15,17 +15,17 @@ const StatusSelector: FC<StatusSelectorProps> = ({ id, value, onChange, allowEmp
<select
id={`${id}-status`}
className={css({
width: '100%',
border: 'none',
background: 'transparent',
color: 'inherit',
outline: 'none',
cursor: 'pointer',
fontSize: 'inherit',
fontWeight: 'inherit',
lineHeight: 'inherit',
padding: '0',
borderRadius: '0',
'width': '100%',
'border': 'none',
'background': 'transparent',
'color': 'inherit',
'outline': 'none',
'cursor': 'pointer',
'fontSize': 'inherit',
'fontWeight': 'inherit',
'lineHeight': 'inherit',
'padding': '0',
'borderRadius': '0',
'&:focus': {
outline: 'none'
}
+6 -9
View File
@@ -25,9 +25,9 @@ const getTeams = async (): Promise<GetTeamsResponse> => {
const moderatorMembers: Models.MembershipList = await getClanMembers(MODERATOR_CLAN_ID)
const collaboratorMembers: Models.MembershipList = await getClanMembers(COLLABORATOR_CLAN_ID)
const adminsPromises = adminMembers.memberships.map(async membership => await getUser(membership.userId))
const moderatorsPromises = moderatorMembers.memberships.map(async membership => await getUser(membership.userId))
const collaboratorsPromises = collaboratorMembers.memberships.map(async membership => await getUser(membership.userId))
const adminsPromises = adminMembers.memberships.map(async (membership) => await getUser(membership.userId))
const moderatorsPromises = moderatorMembers.memberships.map(async (membership) => await getUser(membership.userId))
const collaboratorsPromises = collaboratorMembers.memberships.map(async (membership) => await getUser(membership.userId))
const [admins, moderators, collaborators] = await Promise.all([
Promise.all(adminsPromises), Promise.all(moderatorsPromises), Promise.all(collaboratorsPromises)
@@ -96,8 +96,7 @@ const EquipoPage: FC = async () => {
<Typography variant="body2" color="info">
Ups, parece que ahora mismo no hay administradores, pero en EntGamers siempre estamos estamos buscando gente que quiera organizar cosas para la comunidad, puedes contactarnos para formar parte de nuestro equipo haciendo click en el siguiente enlace.
</Typography>
)
}
)}
<div className={center()}>
<NextLink
className={button({ color: 'info' })}
@@ -158,8 +157,7 @@ const EquipoPage: FC = async () => {
<Typography variant="body2" color="info">
Ups, parece que ahora mismo no hay moderadores, pero en EntGamers siempre estamos buscando gente que quiera ayudar a la comunidad. si quieres ser moderador, puedes hacer click en el botón de abajo.
</Typography>
)
}
)}
<div className={center()}>
<NextLink
className={button({ color: 'info' })}
@@ -220,8 +218,7 @@ const EquipoPage: FC = async () => {
<Typography variant="body2" color="info">
Ups, parece que ahora mismo no hay colaboradores, pero en EntGamers siempre estamos buscando gente que quiera ayudar a la comunidad. si quieres ser colaborador, puedes hacer click en el botón de abajo.
</Typography>
)
}
)}
<div className={center()}>
<NextLink
className={button({ color: 'info' })}
+80 -60
View File
@@ -16,11 +16,14 @@ import { ADMIN_CLAN_ID, COLLABORATOR_CLAN_ID, MODERATOR_CLAN_ID } from 'entgamer
import { createTeamApplication, type TeamApplicationData } from 'entgamers-database/frontend/database/teamApplications'
import { useFormik } from 'formik'
import { AnimatePresence, motion } from 'framer-motion'
import { useSearchParams } from 'next/navigation'
import { usePathname, useSearchParams } from 'next/navigation'
import { useRouter } from 'next/router'
import { useEffect, type FC } from 'react'
const ApplyForm: FC = () => {
const searchParams = useSearchParams()
const pathname = usePathname()
const router = useRouter()
const { manageError } = useManageError()
const dispatch = useAppDispatch()
@@ -54,8 +57,11 @@ const ApplyForm: FC = () => {
.catch((error) => {
console.error(error)
})
.finally(() => {
router.replace(pathname)
})
}
}, [])
}, [searchParams, formik, pathname, router])
return (
<form
@@ -70,7 +76,7 @@ const ApplyForm: FC = () => {
})}
>
<Button
type='button'
type="button"
onClick={() => {
formik.setFieldValue('role', MODERATOR_CLAN_ID)
.catch((error) => {
@@ -82,7 +88,7 @@ const ApplyForm: FC = () => {
Moderador
</Button>
<Button
type='button'
type="button"
onClick={() => {
formik.setFieldValue('role', ADMIN_CLAN_ID)
.catch((error) => {
@@ -94,7 +100,7 @@ const ApplyForm: FC = () => {
Administrador
</Button>
<Button
type='button'
type="button"
onClick={() => {
formik.setFieldValue('role', COLLABORATOR_CLAN_ID)
.catch((error) => {
@@ -121,90 +127,87 @@ const ApplyForm: FC = () => {
})}
>
<FormGroup>
<label htmlFor='name'>Nombre</label>
<label htmlFor="name">Nombre</label>
<Input
id='name'
type='text'
id="name"
type="text"
value={formik.values.name}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.name !== undefined && formik.errors.name !== undefined
? (
<Typography variant='caption' color='danger'>
<Typography variant="caption" color="danger">
{formik.errors.name}
</Typography>
)
: (
<Typography variant='caption' color='info'>
<Typography variant="caption" color="info">
Tu nombre.
</Typography>
)}
</FormGroup>
<FormGroup>
<label htmlFor='email'>Email</label>
<label htmlFor="email">Email</label>
<Input
id='email'
type='email'
id="email"
type="email"
value={formik.values.email}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.email !== undefined && formik.errors.email !== undefined
? (
<Typography variant='caption' color='danger'>
<Typography variant="caption" color="danger">
{formik.errors.email}
</Typography>
)
: (
<Typography variant='caption' color='info'>
<Typography variant="caption" color="info">
Tu email, para poder contactarte.
</Typography>
)
}
)}
</FormGroup>
<FormGroup>
<label htmlFor='discord'>Nombre de Discord</label>
<label htmlFor="discord">Nombre de Discord</label>
<Input
id='discord'
type='text'
id="discord"
type="text"
value={formik.values.discord}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.discord !== undefined && formik.errors.discord !== undefined
? (
<Typography variant='caption' color='danger'>
<Typography variant="caption" color="danger">
{formik.errors.discord}
</Typography>
)
: (
<Typography variant='caption' color='info'>
<Typography variant="caption" color="info">
Tu nombre de Discord, para poder contactarte.
</Typography>
)
}
)}
</FormGroup>
<FormGroup>
<label htmlFor='message'>Mensaje</label>
<label htmlFor="message">Mensaje</label>
<TextArea
id='message'
id="message"
value={formik.values.message}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.message !== undefined && formik.errors.message !== undefined
? (
<Typography variant='caption' color='danger'>
<Typography variant="caption" color="danger">
{formik.errors.message}
</Typography>
)
: (
<Typography variant='caption' color='info'>
<Typography variant="caption" color="info">
¿Por que te gustaría unirte al equipo?, ¿Que te gustaría hacer?, etc.
</Typography>
)
}
)}
</FormGroup>
<div
className={css({
@@ -212,7 +215,7 @@ const ApplyForm: FC = () => {
})}
>
<Button
type='submit'
type="submit"
disabled={!formik.isValid || !formik.dirty}
fullWidth
@@ -239,14 +242,13 @@ const ApplyForm: FC = () => {
justifyContent: 'center'
})}
>
<Typography variant='h2' align="center">¡Gracias por interesarte en unirte al equipo!</Typography>
<Typography variant='body1'>
<Typography variant="h2" align="center">¡Gracias por interesarte en unirte al equipo!</Typography>
<Typography variant="body1">
El equipo de EntGamers se pondrá en contacto contigo a la brevedad posible.
</Typography>
</div>
</div>
)
}
)}
<div
className={css({
overflow: 'hidden',
@@ -254,31 +256,35 @@ const ApplyForm: FC = () => {
paddingBlock: 'medium'
})}
>
<AnimatePresence mode='wait' initial={false}>
<AnimatePresence mode="wait" initial={false}>
{formik.values.role === MODERATOR_CLAN_ID && (
<motion.div
key={'motion-moderator'}
key="motion-moderator"
transition={{ duration: 0.15, ease: 'easeInOut' }}
initial={{ opacity: 0, x: '-250px' }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: '250px' }}
>
<Typography variant='h2' align="center">Moderadores</Typography>
<Typography variant='body1'>
<Typography variant="h2" align="center">Moderadores</Typography>
<Typography variant="body1">
El equipo de moderación de EntGamers se encarga de moderar los distintos espacios en los que se desenvuelve la comunidad, como los grupos de Facebook, Discord, Etc.
</Typography>
<Typography variant='h3'>Requisitos</Typography>
<Typography variant="h3">Requisitos</Typography>
<ul className="fa-ul">
<li>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem /> <strong>Imparcialidad</strong>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem />
{' '}
<strong>Imparcialidad</strong>
<br />
La comunidad esta conformada por amigos y conocidos, por lo tanto es importante poder actuar de forma imparcial y responsable.
</li>
</ul>
<Typography variant='h3'>Beneficios</Typography>
<Typography variant="h3">Beneficios</Typography>
<ul className="fa-ul">
<li>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem /> <strong>Experiencia</strong>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem />
{' '}
<strong>Experiencia</strong>
<br />
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.
</li>
@@ -287,28 +293,32 @@ const ApplyForm: FC = () => {
)}
{formik.values.role === COLLABORATOR_CLAN_ID && (
<motion.div
key={'motion-collaborator'}
key="motion-collaborator"
transition={{ duration: 0.15, ease: 'easeInOut' }}
initial={{ opacity: 0, x: '-250px' }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: '250px' }}
>
<Typography variant='h2' align='center'>Colaborador</Typography>
<Typography variant='body1'>
<Typography variant="h2" align="center">Colaborador</Typography>
<Typography variant="body1">
Los colaboradores son personas ajenas al staff central de EntGamers que nos ayudan a traer contenido, eventos y actividades a la comunidad.
</Typography>
<Typography variant='h3'>Requisitos</Typography>
<Typography variant="h3">Requisitos</Typography>
<ul className="fa-ul">
<li>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem /> <strong>Profesionalismo</strong>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem />
{' '}
<strong>Profesionalismo</strong>
<br />
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.
</li>
</ul>
<Typography variant='h3'>Beneficios</Typography>
<Typography variant="h3">Beneficios</Typography>
<ul className="fa-ul">
<li>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem /> <strong>Apoyo</strong>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem />
{' '}
<strong>Apoyo</strong>
<br />
Puedes contar con el apoyo de la comunidad para tus proyectos, ya sea en forma de difusión, asesoramiento o recursos.
</li>
@@ -317,43 +327,53 @@ const ApplyForm: FC = () => {
)}
{formik.values.role === ADMIN_CLAN_ID && (
<motion.div
key={'motion-administrator'}
key="motion-administrator"
transition={{ duration: 0.15, ease: 'easeInOut' }}
initial={{ opacity: 0, x: '-250px' }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: '250px' }}
>
<Typography variant='h2' align='center'>Administradores</Typography>
<Typography variant='body1'>
<Typography variant="h2" align="center">Administradores</Typography>
<Typography variant="body1">
Los administradores son quienes se encargan de que todo funcione como es debido en la comunidad, desde la moderación de los grupos hasta la organización de eventos y actividades. Son los responsables de que la comunidad siga creciendo y mejorando.
</Typography>
<Typography variant='h3'>Requisitos</Typography>
<Typography variant="h3">Requisitos</Typography>
<ul className="fa-ul">
<li>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem /> <strong>Profesionalismo</strong>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem />
{' '}
<strong>Profesionalismo</strong>
<br />
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.
</li>
<li>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem /> <strong>Constancia</strong>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem />
{' '}
<strong>Constancia</strong>
<br />
La comunidad busca gente que en sus posibilidades sea activa, que pueda estar al tanto de lo que pasa en ella.
</li>
<li>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem /> <strong>Proactividad</strong>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem />
{' '}
<strong>Proactividad</strong>
<br />
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.
</li>
</ul>
<Typography variant='h3'>Beneficios</Typography>
<Typography variant="h3">Beneficios</Typography>
<ul className="fa-ul">
<li>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem /> <strong>Experiencia</strong>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem />
{' '}
<strong>Experiencia</strong>
<br />
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.
</li>
<li>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem /> <strong>Capacitación</strong>
<FontAwesomeIcon icon={faChevronRight as FontAwesomeIconProps['icon']} fixedWidth listItem />
{' '}
<strong>Capacitación</strong>
<br />
La comunidad buscara dar capacitación a sus miembros en lo referido a herramientas y procedimientos utilizados.
</li>
+4 -2
View File
@@ -1,7 +1,7 @@
import Typography from '@/components/ui/Typography'
import { Container } from '@/styled-system/jsx'
import { ensureTeamApplicationsCollection } from 'entgamers-database/backend/database/teamApplications'
import { type FC } from 'react'
import { Suspense, type FC } from 'react'
import ApplyForm from './ApplyForm'
const EquipoUnirsePage: FC = async () => {
@@ -12,7 +12,9 @@ const EquipoUnirsePage: FC = async () => {
<Typography variant="body1">
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.
</Typography>
<ApplyForm />
<Suspense fallback={<Typography variant="body1">Cargando...</Typography>}>
<ApplyForm />
</Suspense>
</Container>
)
}
+4 -2
View File
@@ -57,7 +57,7 @@ const LoginForm: FC = () => {
if (session.status === 'idle' && session.session !== undefined) {
router.push('/')
}
}, [session])
}, [session, router])
return (
<form
@@ -95,7 +95,9 @@ const LoginForm: FC = () => {
)}
</FormGroup>
<Typography variant="caption" color="muted">
¿Perdiste tu contraseña? <NextLink href="/recover-password">Recupérala</NextLink>
¿Perdiste tu contraseña?
{' '}
<NextLink href="/recover-password">Recupérala</NextLink>
</Typography>
<FormGroup>
<Button
+5 -4
View File
@@ -15,8 +15,7 @@ const LoginPage: FC = () => {
container(),
css({
minHeight: 'calc(100vh - 60px - 72px)'
}))
}
}))}
>
<div
className={cx(
@@ -41,8 +40,10 @@ const LoginPage: FC = () => {
className={card().content}
>
<LoginForm />
<Typography variant="caption" align="center" >
¿No tienes una cuenta? <NextLink href="/register">Regístrate</NextLink>
<Typography variant="caption" align="center">
¿No tienes una cuenta?
{' '}
<NextLink href="/register">Regístrate</NextLink>
</Typography>
</div>
</div>
@@ -68,10 +68,11 @@ const CreateRecoverPasswordForm: FC = () => {
{formik.errors.email}
</Typography>
)
: (<Typography variant="caption" color="info">
Por favor, introduce el correo electrónico con el que te has registrado. Te enviaremos un correo con instrucciones para la recuperación de contraseña
</Typography>)
}
: (
<Typography variant="caption" color="info">
Por favor, introduce el correo electrónico con el que te has registrado. Te enviaremos un correo con instrucciones para la recuperación de contraseña
</Typography>
)}
</FormGroup>
<FormGroup>
<Button
@@ -1,27 +1,23 @@
'use client'
import CreateRecoverPasswordForm from '@/app/recover-password/CreateRecoverPasswordForm'
import { useSearchParams } from 'next/navigation'
import { useEffect, useState, type FC } from 'react'
import type { FC } from 'react'
import UpdateRecoverPasswordForm, { type UpdateRecoverPasswordFormProps } from './UpdateRecoverPasswordForm'
const ManageRecoverPassword: FC = () => {
const [recoverData, setRecoverData] = useState<UpdateRecoverPasswordFormProps | undefined>()
const searchParams = useSearchParams()
useEffect(() => {
const userId = searchParams.get('userId')
const secret = searchParams.get('secret')
if (userId !== null && secret !== null) {
setRecoverData({ userId, secret })
}
}, [])
const userId = searchParams.get('userId')
const secret = searchParams.get('secret')
const recoverData: UpdateRecoverPasswordFormProps | undefined = (userId !== null && secret !== null) ? { userId, secret } : undefined
if (recoverData === undefined) {
return <CreateRecoverPasswordForm />
} else {
return <UpdateRecoverPasswordForm
{...recoverData}
/>
return (
<UpdateRecoverPasswordForm
{...recoverData}
/>
)
}
}
@@ -89,8 +89,7 @@ const UpdateRecoverPasswordForm: FC<UpdateRecoverPasswordFormProps> = (props) =>
<Typography variant="caption" color="info">
Escribe tu nueva contraseña
</Typography>
)
}
)}
</FormGroup>
<FormGroup>
<label htmlFor="confirmPassword">
+1 -2
View File
@@ -13,8 +13,7 @@ const page: FC = () => {
container(),
css({
minHeight: 'calc(100vh - 60px - 72px)'
}))
}
}))}
>
<div
className={cx(
+5 -4
View File
@@ -15,8 +15,7 @@ const RegisterPage: FC = () => {
container(),
css({
minHeight: 'calc(100vh - 60px - 72px)'
}))
}
}))}
>
<div
@@ -42,8 +41,10 @@ const RegisterPage: FC = () => {
className={card().content}
>
<RegisterForm />
<Typography variant="caption" align="center" >
¿Ya tienes una cuenta? <NextLink href="/login">Inicia sesión</NextLink>
<Typography variant="caption" align="center">
¿Ya tienes una cuenta?
{' '}
<NextLink href="/login">Inicia sesión</NextLink>
</Typography>
</div>
</div>
+18 -6
View File
@@ -22,14 +22,20 @@ const Footer: FC = () => {
})}
>
<div>
<Typography variant="h3" component='div'> Acerca de </Typography>
<Typography variant="h3" component="div"> Acerca de </Typography>
<ul className="fa-ul">
<li><FontAwesomeIcon icon={faChevronRight} listItem fixedWidth /><NextLink href="/acerca-de"> EntGamers</NextLink></li>
<li><FontAwesomeIcon icon={faChevronRight} listItem fixedWidth /><NextLink href="/clanes"> Clanes</NextLink></li>
<li>
<FontAwesomeIcon icon={faChevronRight} listItem fixedWidth />
<NextLink href="/acerca-de"> EntGamers</NextLink>
</li>
<li>
<FontAwesomeIcon icon={faChevronRight} listItem fixedWidth />
<NextLink href="/clanes"> Clanes</NextLink>
</li>
</ul>
</div>
<div>
<Typography variant="h3" component='div'> Contacto </Typography>
<Typography variant="h3" component="div"> Contacto </Typography>
</div>
<div></div>
</Container>
@@ -40,8 +46,14 @@ const Footer: FC = () => {
justifyContent: 'center'
})}
>
<Typography variant="body2" component='div'>
Hecho con <FontAwesomeIcon className={css({ color: 'red' })} icon={faHeart} /> por <a href="https://srjuggernaut.dev">SrJuggernaut</a>
<Typography variant="body2" component="div">
Hecho con
{' '}
<FontAwesomeIcon className={css({ color: 'red' })} icon={faHeart} />
{' '}
por
{' '}
<a href="https://srjuggernaut.dev">SrJuggernaut</a>
</Typography>
</Container>
</footer>
+17 -17
View File
@@ -21,28 +21,28 @@ const Header: FC = () => {
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
}, [handleScroll])
return (
<>
<header
className={css({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'transparent',
color: 'text',
minHeight: '60px',
position: 'fixed',
top: 0,
left: 0,
width: '100%',
zIndex: 'sticky',
boxShadow: 'none',
transitionProperty: 'background-color, box-shadow',
transitionDuration: '0.25s',
transitionTimingFunction: 'easeInOut',
willChange: 'background-color, box-shadow',
'display': 'flex',
'alignItems': 'center',
'justifyContent': 'center',
'backgroundColor': 'transparent',
'color': 'text',
'minHeight': '60px',
'position': 'fixed',
'top': 0,
'left': 0,
'width': '100%',
'zIndex': 'sticky',
'boxShadow': 'none',
'transitionProperty': 'background-color, box-shadow',
'transitionDuration': '0.25s',
'transitionTimingFunction': 'easeInOut',
'willChange': 'background-color, box-shadow',
'&[data-scrolled=true]': {
backgroundColor: 'surface',
boxShadow: '2px 2px 4px 0px rgba(0, 0, 0, 0.25)'
+10 -10
View File
@@ -14,7 +14,7 @@ import NextLink from 'next/link'
import { type FC } from 'react'
const SessionButtons: FC = () => {
const { session, status, clanes } = useAppSelector(state => state.session)
const { session, status, clanes } = useAppSelector((state) => state.session)
const { manageError } = useManageError()
const dispatch = useAppDispatch()
@@ -24,8 +24,8 @@ const SessionButtons: FC = () => {
return (
<>
<Tooltip
title={'Iniciar sesión'}
position='bottom'
title="Iniciar sesión"
position="bottom"
>
<NextLink
href="/login"
@@ -44,8 +44,8 @@ const SessionButtons: FC = () => {
return (
<>
<Tooltip
title={'Mi cuenta'}
position='bottom'
title="Mi cuenta"
position="bottom"
>
<NextLink
href="/cuenta"
@@ -56,10 +56,10 @@ const SessionButtons: FC = () => {
<FontAwesomeIcon icon={faUser} fixedWidth />
</NextLink>
</Tooltip>
{clanes !== undefined && clanes?.teams.some(team => team.$id === ADMIN_CLAN_ID || team.$id === MODERATOR_CLAN_ID) && (
{clanes !== undefined && clanes?.teams.some((team) => team.$id === ADMIN_CLAN_ID || team.$id === MODERATOR_CLAN_ID) && (
<Tooltip
title={'Panel de administración'}
position='bottom'
title="Panel de administración"
position="bottom"
>
<NextLink
href="/dashboard"
@@ -72,8 +72,8 @@ const SessionButtons: FC = () => {
</Tooltip>
)}
<Tooltip
title={'Cerrar sesión'}
position='bottom'
title="Cerrar sesión"
position="bottom"
>
<IconButton
onClick={() => {
+18 -15
View File
@@ -3,7 +3,7 @@ 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'
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
import { faBars, faHome, faTimes, faUsers } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import NextLink from 'next/link'
@@ -62,6 +62,7 @@ const Menu: FC = () => {
})}
>
<button
type="button"
className={iconButton({
color: 'danger'
})}
@@ -80,22 +81,21 @@ const Menu: FC = () => {
>
{menuLinks.map((menuLink, index) => (
<li
key={`menu-link-${index}`}
onClick={() => { setIsMenuOpen(false) }}
key={`menu-link-${menuLink.label}-${index.toString()}`}
>
<NextLink
className={css({
display: 'flex',
alignItems: 'center',
justifyContent: 'left',
padding: '1rem',
textDecoration: 'none',
backgroundColor: 'transparent',
color: 'text',
transitionProperty: 'background-color',
transitionDuration: 'normal',
transitionTimingFunction: 'easeInOut',
willChange: 'background-color color',
'display': 'flex',
'alignItems': 'center',
'justifyContent': 'left',
'padding': '1rem',
'textDecoration': 'none',
'backgroundColor': 'transparent',
'color': 'text',
'transitionProperty': 'background-color',
'transitionDuration': 'normal',
'transitionTimingFunction': 'easeInOut',
'willChange': 'background-color color',
'&:hover': {
backgroundColor: 'primary',
color: 'primary.contrast'
@@ -107,8 +107,11 @@ const Menu: FC = () => {
})}
href={menuLink.href}
data-active={pathName === menuLink.href}
onClick={() => { setIsMenuOpen(false) }}
>
<FontAwesomeIcon icon={menuLink.icon} fixedWidth />&nbsp;{menuLink.label}
<FontAwesomeIcon icon={menuLink.icon} fixedWidth />
&nbsp;
{menuLink.label}
</NextLink>
</li>
))}
+2 -3
View File
@@ -32,9 +32,8 @@ export const AlertCloseButton: FC<ComposedAlertCloseButtonProps> = ({ children,
{...allOtherAlertProps}
>
{children === undefined
? <FontAwesomeIcon icon={faTimes as FontAwesomeIconProps['icon']} fixedWidth size='sm' />
: children
}
? <FontAwesomeIcon icon={faTimes as FontAwesomeIconProps['icon']} fixedWidth size="sm" />
: children}
</IconButton>
)
}
+1 -2
View File
@@ -38,8 +38,7 @@ const BackDrop: FC<BackDropProps> = ({ isOpen, onClickAway, children }) => {
{children}
</motion.div>
)
: undefined
}
: undefined}
</AnimatePresence>
), document.body)
}
+3 -5
View File
@@ -1,11 +1,9 @@
import { cx } from '@/styled-system/css'
import { button, type ButtonVariantProps } from '@/styled-system/recipes/button'
import { type MergeOmitting } from '@/types/utilities'
import { type ButtonHTMLAttributes, type DetailedHTMLProps, type FC } from 'react'
import type { MergeOmitting } from '@/types/utilities'
import type { ButtonHTMLAttributes, DetailedHTMLProps, FC } from 'react'
type ComposedButtonProps = MergeOmitting<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, ButtonVariantProps>
export interface ButtonProps extends ComposedButtonProps {}
export type ButtonProps = MergeOmitting<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, ButtonVariantProps>
const Button: FC<ButtonProps> = ({ children, className, ...rest }) => {
const [buttonRecipeArgs, allOtherButtonProps] = button.splitVariantProps(rest)
+3 -5
View File
@@ -1,11 +1,9 @@
import { cx } from '@/styled-system/css'
import { iconButton, type IconButtonVariantProps } from '@/styled-system/recipes/icon-button'
import { type MergeOmitting } from '@/types/utilities'
import { type ButtonHTMLAttributes, type DetailedHTMLProps, type FC } from 'react'
import type { MergeOmitting } from '@/types/utilities'
import type { ButtonHTMLAttributes, DetailedHTMLProps, FC } from 'react'
type ComposedIconButtonProps = MergeOmitting<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, IconButtonVariantProps>
export interface IconButtonProps extends ComposedIconButtonProps {}
export type IconButtonProps = MergeOmitting<DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, IconButtonVariantProps>
const IconButton: FC<IconButtonProps> = ({ children, className, ...rest }) => {
const [iconButtonRecipeArgs, allOtherIconButtonProps] = iconButton.splitVariantProps(rest)
+9 -10
View File
@@ -1,7 +1,7 @@
import { cx } from '@/styled-system/css'
import { typography, type TypographyVariantProps } from '@/styled-system/recipes/typography'
import { type MergeOmitting } from '@/types/utilities'
import { type ElementType, type FC, type HTMLAttributes } from 'react'
import type { MergeOmitting } from '@/types/utilities'
import { type ElementType, type FC, type HTMLAttributes, createElement } from 'react'
type ComposedTypographyProps = MergeOmitting<HTMLAttributes<HTMLElement>, TypographyVariantProps>
@@ -35,19 +35,18 @@ const variantToComponent = (variant: TypographyVariantProps['variant']): Element
const Typography: FC<TypographyProps> = ({ children, className, component, ...rest }) => {
const [typographyRecipeArgs, allOtherTypographyProps] = typography.splitVariantProps(rest)
const Component = component ?? variantToComponent(typographyRecipeArgs.variant)
typographyRecipeArgs.color = typographyRecipeArgs.color ?? (
typeof typographyRecipeArgs.variant === 'string' && typographyRecipeArgs.variant.startsWith('h')
? 'primary'
: 'inherit'
)
return (
<Component
className={cx(typography(typographyRecipeArgs), className)}
{...allOtherTypographyProps}
>
{children}
</Component>
return createElement(
component ?? variantToComponent(typographyRecipeArgs.variant),
{
className: cx(typography(typographyRecipeArgs), className),
...allOtherTypographyProps
},
children
)
}
+5 -3
View File
@@ -19,14 +19,16 @@ const DebouncedInput: FC<DebouncedInputProps> = ({ value: initialValue, onChange
onChange(value)
}, debounce)
return () => { clearTimeout(timeout) }
}, [value])
return () => {
clearTimeout(timeout)
}
}, [value, onChange, debounce])
return (
<Input
{...props}
value={value}
onChange={e => { setValue(e.target.value) }}
onChange={(e) => { setValue(e.target.value) }}
/>
)
}
+5 -9
View File
@@ -1,21 +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'
import type { MergeOmitting } from '@/types/utilities'
import type { DetailedHTMLProps, FC, InputHTMLAttributes } from 'react'
type ComposedInputProps = MergeOmitting<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, InputVariantProps>
export type InputProps = MergeOmitting<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, InputVariantProps>
export interface InputProps extends ComposedInputProps {}
const Input: FC<InputProps> = ({ children, className, ...rest }) => {
const Input: FC<InputProps> = ({ className, ...rest }) => {
const [inputRecipeArgs, allOtherInputProps] = input.splitVariantProps(rest)
return (
<input
className={cx(input(inputRecipeArgs), className)}
{...allOtherInputProps}
>
{children}
</input>
/>
)
}
+1 -1
View File
@@ -47,7 +47,7 @@ const PasswordInput: FC<InputProps> = ({ className, ...props }) => {
size="small"
onClick={() => { setShowPassword(!showPassword) }}
>
<FontAwesomeIcon icon={showPassword ? faEyeSlash : faEye} fixedWidth/>
<FontAwesomeIcon icon={showPassword ? faEyeSlash : faEye} fixedWidth />
</IconButton>
</Tooltip>
</div>
+3 -3
View File
@@ -13,16 +13,16 @@ const feedbackSlice = createSlice({
name: 'feedback',
initialState,
reducers: {
addAlert (state, action: PayloadAction<Alert>) {
addAlert(state, action: PayloadAction<Alert>) {
return {
...state,
alerts: [...state.alerts, action.payload]
}
},
removeAlert (state, action: PayloadAction<string>) {
removeAlert(state, action: PayloadAction<string>) {
return {
...state,
alerts: state.alerts.filter(alert => alert.id !== action.payload)
alerts: state.alerts.filter((alert) => alert.id !== action.payload)
}
}
}
+10 -10
View File
@@ -1,15 +1,15 @@
import { createSlice, type PayloadAction } from '@reduxjs/toolkit'
import { type Models } from 'appwrite'
import { type ClanList } from 'entgamers-database/frontend/clanes'
import { type User } from 'entgamers-database/frontend/session'
import type { Models } from 'appwrite'
import type { ClanList } from 'entgamers-database/frontend/clanes'
import type { User } from 'entgamers-database/frontend/session'
export type SessionState =
| {
status: 'idle' | 'loading' | 'initializing'
session?: Models.Session
user?: User
clanes?: ClanList
}
export type SessionState
= | {
status: 'idle' | 'loading' | 'initializing'
session?: Models.Session
user?: User
clanes?: ClanList
}
const initialState: SessionState = {
status: 'initializing'
+4 -3
View File
@@ -16,7 +16,7 @@
"moduleResolution": "Node16",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"jsx": "react-jsx",
"incremental": true,
"baseUrl": "src",
"paths": {
@@ -35,9 +35,10 @@
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"next.config.js"
"next.config.js",
".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}
}