├── vite-env.d.ts ├── .husky └── pre-commit ├── vercel.json ├── public ├── logo.png └── images │ ├── rules │ ├── rule_1.webp │ ├── rule_2.webp │ ├── rule_3.webp │ └── rule_4.webp │ ├── rewards │ ├── mx_keys.webp │ ├── mx_master_3s.webp │ ├── webcam_mx_brio.webp │ ├── alfombrilla_logitech.webp │ ├── bronze_medal.svg │ ├── silver_medal.svg │ └── gold_medal.svg │ ├── faqs │ └── chevron.svg │ └── sponsors │ ├── getmagical.svg │ ├── logitech.svg │ └── 4geeks.svg ├── src ├── components │ ├── Regulation.tsx │ ├── common │ │ ├── Title.tsx │ │ ├── Rule.tsx │ │ ├── Button.tsx │ │ ├── ButtonLink.tsx │ │ └── Award.tsx │ ├── Footer.tsx │ ├── CTASection.tsx │ ├── Home.tsx │ ├── Sponsors.tsx │ ├── FAQ.tsx │ ├── Hero.tsx │ ├── Register │ │ ├── components │ │ │ ├── TermsAndConditions.tsx │ │ │ ├── ProjectForm.tsx │ │ │ ├── Input.tsx │ │ │ └── Participants.tsx │ │ ├── zod.schema.ts │ │ └── index.tsx │ ├── Rules.tsx │ ├── Awards.tsx │ ├── QACollapse.tsx │ └── Nav.tsx ├── constants.ts ├── routes │ └── index.ts ├── main.tsx ├── common │ └── utils │ │ └── cn.ts ├── App.tsx ├── index.css └── data │ └── faqs.ts ├── vite.config.ts ├── tsconfig.node.json ├── .prettierrc ├── index.html ├── .gitignore ├── .eslintrc.cjs ├── tsconfig.json ├── uno.config.ts ├── package.json └── README.md /vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | # .husky/pre-commit 2 | npx lint-staged 3 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }] } 2 | -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/afordigital/hackaton-del-dev/HEAD/public/logo.png -------------------------------------------------------------------------------- /src/components/Regulation.tsx: -------------------------------------------------------------------------------- 1 | export const Regulation = () => { 2 | return <>Regulation 3 | } 4 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | 2 | export enum AWARD_TYPE { 3 | PRICE= 'PRICE', 4 | GIFT = 'GIFT' 5 | } 6 | -------------------------------------------------------------------------------- /public/images/rules/rule_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/afordigital/hackaton-del-dev/HEAD/public/images/rules/rule_1.webp -------------------------------------------------------------------------------- /public/images/rules/rule_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/afordigital/hackaton-del-dev/HEAD/public/images/rules/rule_2.webp -------------------------------------------------------------------------------- /public/images/rules/rule_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/afordigital/hackaton-del-dev/HEAD/public/images/rules/rule_3.webp -------------------------------------------------------------------------------- /public/images/rules/rule_4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/afordigital/hackaton-del-dev/HEAD/public/images/rules/rule_4.webp -------------------------------------------------------------------------------- /public/images/rewards/mx_keys.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/afordigital/hackaton-del-dev/HEAD/public/images/rewards/mx_keys.webp -------------------------------------------------------------------------------- /src/routes/index.ts: -------------------------------------------------------------------------------- 1 | export const ROUTE = { 2 | home: '/', 3 | register: '/register', 4 | regulation: '/regulation', 5 | } 6 | -------------------------------------------------------------------------------- /public/images/rewards/mx_master_3s.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/afordigital/hackaton-del-dev/HEAD/public/images/rewards/mx_master_3s.webp -------------------------------------------------------------------------------- /public/images/rewards/webcam_mx_brio.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/afordigital/hackaton-del-dev/HEAD/public/images/rewards/webcam_mx_brio.webp -------------------------------------------------------------------------------- /public/images/rewards/alfombrilla_logitech.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/afordigital/hackaton-del-dev/HEAD/public/images/rewards/alfombrilla_logitech.webp -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import UnoCSS from 'unocss/vite' 4 | 5 | export default defineConfig({ 6 | plugins: [react(), UnoCSS()] 7 | }) 8 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "useTabs": false, 4 | "semi": false, 5 | "singleQuote": true, 6 | "jsxSingleQuote": false, 7 | "trailingComma": "none", 8 | "bracketSpacing": true, 9 | "bracketSameLine": false, 10 | "arrowParens": "always" 11 | } 12 | -------------------------------------------------------------------------------- /src/components/common/Title.tsx: -------------------------------------------------------------------------------- 1 | type TitleProps = { 2 | children: string 3 | } 4 | 5 | export const Title = ({ children }: TitleProps) => { 6 | return ( 7 |

8 | {children} 9 |

10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /src/components/Footer.tsx: -------------------------------------------------------------------------------- 1 | export const Footer = () => { 2 | return ( 3 | 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /src/components/CTASection.tsx: -------------------------------------------------------------------------------- 1 | import { ButtonLink } from "./common/ButtonLink" 2 | import { Title } from "./common/Title" 3 | 4 | 5 | 6 | export const CTASection = () => { 7 | return ( 8 |
9 | Busca un equipo y regístrate 10 | Registrarme 11 |
12 | ) 13 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hackaton del dev 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | 27 | # locks 28 | package-lock.json 29 | yarn.lock 30 | pnpm-lock.yaml 31 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App' 4 | 5 | import '@unocss/reset/tailwind-compat.css' 6 | import 'virtual:uno.css' 7 | import './index.css' 8 | import { BrowserRouter } from 'react-router-dom' 9 | 10 | ReactDOM.createRoot(document.getElementById('root')!).render( 11 | 12 | 13 | 14 | 15 | 16 | ) 17 | -------------------------------------------------------------------------------- /src/components/common/Rule.tsx: -------------------------------------------------------------------------------- 1 | type RuleProps = { 2 | id: number 3 | alt: string 4 | description: string 5 | } 6 | 7 | export const Rule = ({ id, alt, description }: RuleProps) => { 8 | return ( 9 |
10 | {alt} 11 |

12 | {description} 13 |

14 |
15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended' 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true } 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/components/common/Button.tsx: -------------------------------------------------------------------------------- 1 | type ButtonProps = { 2 | children: React.ReactNode 3 | onClick: () => void 4 | } 5 | 6 | export const Button = ({ children, onClick }: ButtonProps) => { 7 | return ( 8 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /src/components/Home.tsx: -------------------------------------------------------------------------------- 1 | import { Awards } from './Awards' 2 | import { CTASection } from './CTASection' 3 | import { Faq } from './FAQ' 4 | import { Hero } from './Hero' 5 | import { Rules } from './Rules' 6 | import { Sponsors } from './Sponsors' 7 | 8 | export const Home = () => { 9 | return ( 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /src/components/common/ButtonLink.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | import { Link } from 'react-router-dom' 3 | import { ROUTE } from '../../routes' 4 | 5 | type Props = { 6 | to: keyof typeof ROUTE 7 | children: React.ReactNode 8 | } 9 | 10 | export const ButtonLink: FC = ({ to, children }) => { 11 | return ( 12 | 16 |

{children}

17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/components/Sponsors.tsx: -------------------------------------------------------------------------------- 1 | import { Title } from './common/Title' 2 | 3 | export const Sponsors = () => { 4 | return ( 5 |
9 | Patrocinadores 10 |
11 | logitech logo 12 | getmagical logo 13 | 4geeks logo 14 |
15 |
16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/common/utils/cn.ts: -------------------------------------------------------------------------------- 1 | import { ClassValue, clsx } from 'clsx' 2 | import { twMerge } from 'tailwind-merge' 3 | 4 | /** 5 | * Combines and merges Tailwind CSS classes using twMerge and clsx utility functions. 6 | * twMerge is used to handle conflicts between classes effectively. 7 | * 8 | * @param {...ClassValue} inputs - An array of class values to be combined and merged. 9 | * @returns {string} - The merged and combined class names as a string. 10 | */ 11 | export const cn = (...inputs: ClassValue[]) => { 12 | return twMerge(clsx(inputs)) 13 | } 14 | 15 | /** 16 | * Source: 17 | * Tailwind merge: https://github.com/dcastil/tailwind-merge/tree/v1.14.0 18 | */ 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [ 21 | { 22 | "path": "./tsconfig.node.json" 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/components/common/Award.tsx: -------------------------------------------------------------------------------- 1 | import { AWARD_TYPE } from '../../constants' 2 | 3 | type AwardProps = { 4 | img: string 5 | alt: string 6 | title: string 7 | awardType: AWARD_TYPE 8 | } 9 | 10 | export const Award = ({ img, alt, title, awardType }: AwardProps) => { 11 | return ( 12 |
15 | {alt} 16 | 17 |

20 | {title} 21 |

22 |
23 | ) 24 | } 25 | 26 | // flex-col items-end md:flex-row md:items-center even:items-center 27 | -------------------------------------------------------------------------------- /src/components/FAQ.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | import { faqs } from '../data/faqs' 3 | import { QACollapse } from './QACollapse' 4 | import { Title } from './common/Title' 5 | 6 | export const Faq = () => { 7 | const [expandedFaq, setExpandedFaq] = useState(null) 8 | 9 | const handleExpanderClick = (id: string) => { 10 | setExpandedFaq((prev) => (prev === id ? null : id)) 11 | } 12 | const renderFaqs = () => 13 | faqs.map((faq) => ( 14 | 22 | )) 23 | 24 | return ( 25 |
26 | Faqs 27 | {renderFaqs()} 28 |
29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /public/images/faqs/chevron.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/components/Hero.tsx: -------------------------------------------------------------------------------- 1 | import Spline from '@splinetool/react-spline' 2 | import { ButtonLink } from './common/ButtonLink' 3 | 4 | export const Hero = () => { 5 | return ( 6 |
7 |
8 |

9 | La Hackathon Del Dev 10 |

11 |

12 | Una hackathon para cualquier dev 13 |

14 |

15 | Próxima edición 13 de abril del 2024 16 |

17 | Registrarme 18 |
19 |
20 | 21 |
22 |
23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /src/components/Register/components/TermsAndConditions.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | import { FieldErrors, UseFormRegister } from 'react-hook-form' 3 | import { RegisterForm } from '../zod.schema' 4 | 5 | type Props = { 6 | register: UseFormRegister 7 | errors: FieldErrors 8 | } 9 | 10 | export const TermsAndConditions: FC = ({ register, errors }) => { 11 | return ( 12 |
13 |

14 | 19 | Al enviar mi participación, confirmo que he leído y acepto los{' '} 20 | términos y condiciones de 21 | privacidad. 22 |

23 |

24 | {errors.terms_and_conditions && ( 25 | 26 | {errors.terms_and_conditions.message} 27 | 28 | )} 29 |

30 |
31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /uno.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, presetIcons, presetWebFonts, presetUno } from 'unocss' 2 | 3 | export default defineConfig({ 4 | theme: { 5 | colors: { 6 | cBackground: '#161616', 7 | cPrimary: '#151515', 8 | cSecondary: '#2E2E2E', 9 | cTertiary: '#A8A8A8', 10 | cStrokeBox: '#767676', 11 | cWhite: '#EFEFEF', 12 | cGreenText: '#35D78B', 13 | cGreenButton: '#2F8F62', 14 | cGreenStroke: '#33CA86', 15 | cRed: '#EC3F3F' 16 | }, 17 | dropShadow: { 18 | 'customShadow': '0 0 48px rgba(115, 134, 125, 0.30)', 19 | } 20 | }, 21 | shortcuts: { 22 | 'title-gradient': 23 | 'bg-gradient-to-r text-transparent bg-clip-text from-[#EEF1F0] to-[#555555]' 24 | }, 25 | presets: [ 26 | presetUno(), 27 | presetWebFonts({ 28 | provider: 'google', 29 | fonts: { 30 | inter: 'Inter' 31 | } 32 | }), 33 | presetIcons({ 34 | cdn: 'https://esm.sh/', 35 | extraProperties: { 36 | display: 'inline-block', 37 | 'vertical-align': 'middle' 38 | } 39 | }) 40 | ] 41 | }) 42 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Route, Routes } from 'react-router-dom' 2 | import { Register } from './components/Register' 3 | import { Home } from './components/Home' 4 | import { Toaster } from 'sonner' 5 | import { ROUTE } from './routes' 6 | import { Nav } from './components/Nav' 7 | import { Regulation } from './components/Regulation' 8 | import { Footer } from './components/Footer' 9 | 10 | function App() { 11 | return ( 12 | <> 13 |