diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e5cecc18..a64add40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: jobs: lint: - runs-on: ubuntu-latest + runs-on: self-hosted strategy: matrix: node-version: [18] @@ -33,7 +33,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} build: - runs-on: ubuntu-latest + runs-on: self-hosted strategy: matrix: node-version: [18] @@ -58,34 +58,62 @@ jobs: url: ${{ secrets.SLACK_WEBHOOK_URL }} token: ${{ secrets.GITHUB_TOKEN }} - deploy: - if: ${{ github.event_name != 'pull_request' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/teaser' || github.ref == 'refs/heads/dev') }} - runs-on: ubuntu-latest + deploy-dev: + if: ${{ github.event_name != 'pull_request' && (github.ref == 'refs/heads/dev') }} + runs-on: self-hosted needs: - lint - build - env: - RESOURCE_NAME: ${{ github.ref == 'refs/heads/master' && 'prod-front' || github.ref == 'refs/heads/teaser' && 'prod-teaser' || 'dev-front' }} steps: - - uses: actions/checkout@v3 - - name: Install oc - uses: redhat-actions/oc-installer@v1 + - uses: actions/checkout@v4 + - name: Install docker + uses: docker/setup-buildx-action@v3 + - name: Login to registry + uses: docker/login-action@v3 with: - oc_version: '4.6' - - name: Login to OKD - run: oc login --token=${{ secrets.OKD_TOKEN }} --server=${{ secrets.OKD_SERVER }} - - - name: Change the project - run: oc project ${{ secrets.OKD_PROJECT }} - - - name: Start the build - run: oc start-build ${{ env.RESOURCE_NAME }} --follow - - - uses: lazy-actions/slatify@master - if: ${{ always() }} + registry: ${{ secrets.REGISTRY_URL }} + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v6 with: - type: ${{ job.status }} - job_name: '*Deployment to ${{ env.RESOURCE_NAME }}*' - commit: true - url: ${{ secrets.SLACK_WEBHOOK_URL }} - token: ${{ secrets.GITHUB_TOKEN }} + push: true + build-args: | + NEXT_PUBLIC_API_URL=${{ secrets.NEXT_PUBLIC_API_URL_DEV }} + NEXT_PUBLIC_UPLOADS_URL=${{ secrets.NEXT_PUBLIC_UPLOADS_URL_DEV }} + NEXT_PUBLIC_GOOGLE_VERIFICATION=${{ secrets.NEXT_PUBLIC_GOOGLE_VERIFICATION_DEV }} + NEXT_PUBLIC_URL=${{ secrets.NEXT_PUBLIC_URL_DEV }} + NEXT_PUBLIC_STRIPE_PUBLIC_KEY=${{ secrets.NEXT_PUBLIC_STRIPE_PUBLIC_KEY_DEV }} + ENVIRONMENT=${{ secrets.ENVIRONMENT_DEV }} + tags: | + ${{ secrets.REGISTRY_URL }}/uttarena/front:${{ github.ref == 'refs/heads/master' && 'master' || 'dev' }} + deploy-prod: + if: ${{ github.event_name != 'pull_request' && (github.ref == 'refs/heads/master') }} + runs-on: self-hosted + needs: + - lint + - build + steps: + - uses: actions/checkout@v4 + - name: Install docker + uses: docker/setup-buildx-action@v3 + - name: Login to registry + uses: docker/login-action@v3 + with: + registry: ${{ secrets.REGISTRY_URL }} + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v6 + with: + push: true + build-args: | + NEXT_PUBLIC_API_URL=${{ secrets.NEXT_PUBLIC_API_URL }} + NEXT_PUBLIC_UPLOADS_URL=${{ secrets.NEXT_PUBLIC_UPLOADS_URL }} + NEXT_PUBLIC_GOOGLE_VERIFICATION=${{ secrets.NEXT_PUBLIC_GOOGLE_VERIFICATION }} + NEXT_PUBLIC_URL=${{ secrets.NEXT_PUBLIC_URL }} + NEXT_PUBLIC_STRIPE_PUBLIC_KEY=${{ secrets.NEXT_PUBLIC_STRIPE_PUBLIC_KEY }} + ENVIRONMENT=${{ secrets.ENVIRONMENT }} + tags: | + ${{ secrets.REGISTRY_URL }}/uttarena/front:${{ github.ref == 'refs/heads/master' && 'master' || 'dev' }} + diff --git a/Dockerfile b/Dockerfile index a44f2ba5..944cc950 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,21 @@ FROM node:18 AS base + +ARG NEXT_PUBLIC_API_URL=http://localhost:3000 +ARG NEXT_PUBLIC_UPLOADS_URL=https://arena.dev.uttnetgroup.fr/uploads/files +ARG ROBOTS_INDEX=enabled +ARG NEXT_PUBLIC_GOOGLE_VERIFICATION= +ARG NEXT_PUBLIC_URL=http://localhost:8080 +ARG NEXT_PUBLIC_STRIPE_PUBLIC_KEY= +ARG ENVIRONMENT=developement + +ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL +ENV NEXT_PUBLIC_UPLOADS_URL=$NEXT_PUBLIC_UPLOADS_URL +ENV ROBOTS_INDEX=$ROBOTS_INDEX +ENV NEXT_PUBLIC_GOOGLE_VERIFICATION=$NEXT_PUBLIC_GOOGLE_VERIFICATION +ENV NEXT_PUBLIC_URL=$NEXT_PUBLIC_URL +ENV NEXT_PUBLIC_STRIPE_PUBLIC_KEY=$NEXT_PUBLIC_STRIPE_PUBLIC_KEY +ENV ENVIRONMENT=$ENVIRONMENT + RUN npm install -g pnpm FROM base AS builder @@ -30,4 +47,4 @@ COPY --from=builder --chown=node:node /srv/app/.next/static ./.next/static RUN chown node:node . USER node -CMD ["node", "server.js"] \ No newline at end of file +CMD ["node", "server.js"] diff --git a/src/app/(dashboard)/admin/genbadge/page.tsx b/src/app/(dashboard)/admin/genbadge/page.tsx index 572a6f68..2101a264 100644 --- a/src/app/(dashboard)/admin/genbadge/page.tsx +++ b/src/app/(dashboard)/admin/genbadge/page.tsx @@ -4,7 +4,7 @@ import styles from './style.module.scss'; import { useEffect, useState } from 'react'; import { IconName } from '@/components/UI/Icon'; import { generateBadges } from '@/modules/admin'; -import { Badge, BadgePermission, BadgeType, Commission, CommissionRole } from '@/types'; +import { Badge, BadgePermission, BadgeType, Commission } from '@/types'; import { API } from '@/utils/api'; const GenBadges = () => { @@ -142,7 +142,7 @@ const GenBadges = () => { }} required /> - { const newFields = [...fields!]; - newFields[i] = { ...newFields[i], commissionRole: e as CommissionRole }; + newFields[i] = { ...newFields[i], permission: e as BadgePermission }; setFields(newFields); }} options={[ - { label: 'Membre', value: 'member' }, - { label: 'Responsable', value: 'respo' }, + { label: 'Aucune', value: '' }, + { label: 'Restreint', value: 'restricted' }, + { label: 'Organisateur', value: 'orgaprice' }, + { label: 'Accès total', value: 'fullaccess' }, + { label: 'Invité', value: 'invite' }, ]} required /> + { + const newFields = [...fields!]; + newFields[i] = { ...newFields[i], image: e }; + setFields(newFields); + }} + /> + { + const newFields = [...fields!]; + newFields[i] = { ...newFields[i], place: e }; + setFields(newFields); + }} + /> )} diff --git a/src/app/(dashboard)/admin/genbadge/style.module.scss b/src/app/(dashboard)/admin/genbadge/style.module.scss index 80986e70..2e1144f9 100644 --- a/src/app/(dashboard)/admin/genbadge/style.module.scss +++ b/src/app/(dashboard)/admin/genbadge/style.module.scss @@ -22,7 +22,7 @@ align-items: center; margin-bottom: 2rem; > * { - max-width: 50%; + max-width: 75%; margin-bottom: 0; > * { margin-left: 1rem; @@ -34,7 +34,7 @@ justify-content: space-between; align-items: flex-end; gap: 1rem; - + > button { margin: 1.25rem 0; padding: 0.75rem 1rem; diff --git a/src/app/(dashboard)/admin/settings/page.tsx b/src/app/(dashboard)/admin/settings/page.tsx index ec0c44c3..9d9ae9e8 100644 --- a/src/app/(dashboard)/admin/settings/page.tsx +++ b/src/app/(dashboard)/admin/settings/page.tsx @@ -9,6 +9,7 @@ const Settings = () => { const loginAllowed = useAppSelector((state) => state.settings.login); const shopAllowed = useAppSelector((state) => state.settings.shop); const trombiAllowed = useAppSelector((state) => state.settings.trombi); + const ticketsAllowed = useAppSelector((state) => state.settings.tickets); const changeSetting = (setting: string, value: boolean) => { // TODO: add confirmation modal @@ -18,12 +19,14 @@ const Settings = () => { const changeLogin = (value: boolean) => changeSetting('login', value); const changeShop = (value: boolean) => changeSetting('shop', value); const changeTrombi = (value: boolean) => changeSetting('trombi', value); + const changeTickets = (value: boolean) => changeSetting('tickets', value); return (
+
); }; diff --git a/src/app/(dashboard)/admin/users/page.tsx b/src/app/(dashboard)/admin/users/page.tsx index 05d5dda4..3f756785 100644 --- a/src/app/(dashboard)/admin/users/page.tsx +++ b/src/app/(dashboard)/admin/users/page.tsx @@ -248,7 +248,12 @@ const Users = () => { e.preventDefault(); applySearch(); }}> - + diff --git a/src/app/(dashboard)/dashboard/account/page.tsx b/src/app/(dashboard)/dashboard/account/page.tsx index 547bc42b..b5b6b59a 100644 --- a/src/app/(dashboard)/dashboard/account/page.tsx +++ b/src/app/(dashboard)/dashboard/account/page.tsx @@ -15,6 +15,7 @@ const Account = () => { const dispatch = useAppDispatch(); const user = useAppSelector((state) => state.login.user)!; const team = useAppSelector((state) => state.team.team); + const areTicketsAllowed = useAppSelector((state) => state.settings.tickets); const [firstname, setFirstname] = useState(user.firstname); const [lastname, setLastname] = useState(user.lastname); @@ -36,7 +37,8 @@ const Account = () => { useEffect(() => { setDisplayTicket( - (user.hasPaid && + (areTicketsAllowed && + user.hasPaid && ((user.type !== UserType.coach && user.type !== UserType.player) || (team && team.lockedAt))) as boolean, ); }, [team]); @@ -79,15 +81,15 @@ const Account = () => { } }; - // const downloadTicket = async () => { - // const response = await API.get(`tickets`); + const downloadTicket = async () => { + const response = await API.get(`tickets`); - // const data = window.URL.createObjectURL(response); - // const link = document.createElement('a'); - // link.href = data; - // link.download = 'Billet UTT Arena 2024.pdf'; - // link.click(); - // }; + const data = window.URL.createObjectURL(response); + const link = document.createElement('a'); + link.href = data; + link.download = 'Billet UTT Arena 2024.pdf'; + link.click(); + }; return (
@@ -153,7 +155,7 @@ const Account = () => {
- {/* {displayTicket && ( + {displayTicket && (
Mon billet @@ -162,7 +164,7 @@ const Account = () => { Télécharger mon billet </Button> </div> - )} */} + )} </div> {displayTicket && ( <div className="to-bring"> diff --git a/src/app/page.tsx b/src/app/page.tsx index 51a36de6..f12e8b8a 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,7 +4,7 @@ import Partners from '@/components/Partners'; import Slider from '@/components/landing/Slider'; import Counter from '@/components/landing/Counter'; import BoxContainer from '@/components/landing/BoxContainer'; -import { VerticalDivider, Button, Title, Icon, TextBlock } from '@/components/UI'; +import { VerticalDivider, Button, Title, Icon, TextBlock, YoutubeVideoContainer } from '@/components/UI'; import AppearFromSide from '@/components/UI/AppearFromSide'; import Link from 'next/link'; import ParallaxElementSettings from '@/components/parallax/ParallaxElementSettings'; @@ -65,7 +65,7 @@ const Home = () => { </p> </div> </div>, - /*<YoutubeVideoContainer key={'slide-2'} id="Rapw-tXMeDU" />,*/ + <YoutubeVideoContainer key={'slide-2'} id="geOoiwoYtps" />, <div key={'slide-3'} className={styles.homeHeader}> <div className={styles.content}> <img src={banner.src} alt="Rejoindre l'aventure" loading="lazy" /> @@ -95,7 +95,7 @@ const Home = () => { <BoxContainer title="chiffres.txt" className={styles.boxContainer}> <Counter value={6} name="Tournois" className={styles.sideCounter} /> <VerticalDivider className={styles.divider} /> - <Counter value={4850} valueText=" €" name="de cashprize" className={styles.middleCounter} /> + <Counter value={4900} valueText=" €" name="de cashprize" className={styles.middleCounter} /> <VerticalDivider className={styles.divider} /> <Counter value={416} name="Participants" className={styles.sideCounter} /> </BoxContainer> diff --git a/src/app/tournaments/[id]/content.tsx b/src/app/tournaments/[id]/content.tsx index 38f84fe7..076cee94 100644 --- a/src/app/tournaments/[id]/content.tsx +++ b/src/app/tournaments/[id]/content.tsx @@ -103,59 +103,53 @@ export function TournamentInformation({ tournamentId, animate = true }: { tourna : tournament.casters?.map((caster) => caster.name).join(', ')} </BoxContainer> </div> - {loginAllowed && - status.login && - (status.admin || (status.team && (team?.lockedAt || team?.positionInQueue))) && ( - <> - <Title level={3} type={1} align="center" className={styles.enrolledTeams}> - {tournament.playersPerTeam === 1 ? 'Joueurs inscrits' : 'Équipes inscrites'} :{' '} - {tournament.lockedTeamsCount} / {tournament.maxPlayers / tournament.playersPerTeam} - - - 1 - ? [ - { key: 'name', title: "Nom de l'équipe" }, - // Commented for security reasons - // - // { key: 'players', title: 'Joueurs' }, - ] - : [{ key: 'players', title: 'Joueurs' }] - } - dataSource={tournament.teams - .filter((team) => team.lockedAt) - .map((team) => - tournament.playersPerTeam > 1 - ? { - name: team.name, - // Commented for security reasons - // - players: team.players.map((player) => ( - <> - {player.username} -
- - )), - } - : { - players: team.players.map((player) => ( - <> - {player.username} -
- - )), - }, - )} - /> - - )} + <> + + {tournament.playersPerTeam === 1 ? 'Joueurs inscrits' : 'Équipes inscrites'} : {tournament.lockedTeamsCount}{' '} + / {tournament.maxPlayers / tournament.playersPerTeam} + + +
1 + ? [ + { key: 'name', title: "Nom de l'équipe" }, + // Commented for security reasons + // + // { key: 'players', title: 'Joueurs' }, + ] + : [{ key: 'players', title: 'Joueurs' }] + } + dataSource={tournament.teams + .filter((team) => team.lockedAt) + .map((team) => + tournament.playersPerTeam > 1 + ? { + name: team.name, + // Commented for security reasons + // + players: team.players.map((player) => ( + <> + {player.username} +
+ + )), + } + : { + players: team.players.map((player) => ( + <> + {player.username} +
+ + )), + }, + )} + /> + ); diff --git a/src/components/dashboard/UserModal.tsx b/src/components/dashboard/UserModal.tsx index c53af6b9..7edfebde 100644 --- a/src/components/dashboard/UserModal.tsx +++ b/src/components/dashboard/UserModal.tsx @@ -24,6 +24,7 @@ const permissionOptions = [ { name: 'Vestiaire', value: Permission.repo.toString() }, { name: 'Animation', value: Permission.anim.toString() }, { name: 'Admin', value: Permission.admin.toString() }, + { name: 'Premiers secours', value: Permission.firstaid.toString() }, ]; const typeOptions = [ @@ -275,26 +276,20 @@ const UserModal = ({ containerClassName={styles.userModal}> <> - - + + {(!searchUser || searchUser.type !== UserType.attendant) && ( <> - - + + {!searchUser && ( - + )}