Last active
July 7, 2025 00:16
-
-
Save warderer/393cae36d19a570df4e883855acabee8 to your computer and use it in GitHub Desktop.
[React Hook Form Class] Master in Frontend forms class base code, module 7 class 1 #devf #react
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; | |
| -webkit-font-smoothing: antialiased; | |
| -moz-osx-font-smoothing: grayscale; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| min-height: 100vh; | |
| color: #333; | |
| } | |
| .app { | |
| min-height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .container { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 0 20px; | |
| } | |
| .app-header { | |
| background: rgba(255, 255, 255, 0.1); | |
| backdrop-filter: blur(10px); | |
| border-bottom: 1px solid rgba(255, 255, 255, 0.2); | |
| padding: 2rem 0; | |
| } | |
| .app-title { | |
| font-size: 2.5rem; | |
| font-weight: 700; | |
| color: white; | |
| text-align: center; | |
| margin-bottom: 0.5rem; | |
| } | |
| .app-subtitle { | |
| font-size: 1.1rem; | |
| color: rgba(255, 255, 255, 0.8); | |
| text-align: center; | |
| } | |
| .app-main { | |
| flex: 1; | |
| padding: 3rem 0; | |
| display: flex; | |
| align-items: center; | |
| min-height: calc(100vh - 200px); | |
| height: 100%; | |
| } | |
| .app-footer { | |
| background: rgba(0, 0, 0, 0.1); | |
| backdrop-filter: blur(10px); | |
| border-top: 1px solid rgba(255, 255, 255, 0.1); | |
| padding: 1.5rem 0; | |
| text-align: center; | |
| color: rgba(255, 255, 255, 0.8); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| .newpost-container { | |
| background: white; | |
| border-radius: 20px; | |
| box-shadow: 0 25px 50px rgba(0, 0, 0, 0.1); | |
| padding: 2.5rem; | |
| max-width: 800px; | |
| margin: 0 auto; | |
| } | |
| .newpost-header { | |
| text-align: center; | |
| margin-bottom: 2.5rem; | |
| } | |
| .newpost-header h1 { | |
| font-size: 2.2rem; | |
| font-weight: 600; | |
| color: #2d3748; | |
| margin-bottom: 0.5rem; | |
| } | |
| .newpost-header p { | |
| font-size: 1.1rem; | |
| color: #718096; | |
| } | |
| .newpost-form { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 1.5rem; | |
| } | |
| .form-group { | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .form-row { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 1.5rem; | |
| } | |
| .form-label { | |
| font-weight: 600; | |
| color: #2d3748; | |
| margin-bottom: 0.5rem; | |
| font-size: 0.95rem; | |
| } | |
| .form-input, | |
| .form-textarea, | |
| .form-select { | |
| padding: 0.75rem 1rem; | |
| border: 2px solid #e2e8f0; | |
| border-radius: 12px; | |
| font-size: 1rem; | |
| transition: all 0.3s ease; | |
| background: white; | |
| } | |
| .form-input:focus, | |
| .form-textarea:focus, | |
| .form-select:focus { | |
| outline: none; | |
| border-color: #667eea; | |
| box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); | |
| } | |
| .form-textarea { | |
| resize: vertical; | |
| min-height: 120px; | |
| } | |
| .form-input.error, | |
| .form-textarea.error, | |
| .form-select.error { | |
| border-color: #e53e3e; | |
| } | |
| .error-message { | |
| color: #e53e3e; | |
| font-size: 0.85rem; | |
| margin-top: 0.25rem; | |
| font-weight: 500; | |
| } | |
| .form-actions { | |
| display: flex; | |
| gap: 1rem; | |
| justify-content: flex-end; | |
| margin-top: 1rem; | |
| } | |
| .btn { | |
| padding: 0.75rem 1.5rem; | |
| border: none; | |
| border-radius: 12px; | |
| font-size: 1rem; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| } | |
| .btn-primary { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| } | |
| .btn-primary:hover:not(:disabled) { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3); | |
| } | |
| .btn-primary:disabled { | |
| opacity: 0.6; | |
| cursor: not-allowed; | |
| } | |
| .btn-secondary { | |
| background: #f7fafc; | |
| color: #4a5568; | |
| border: 2px solid #e2e8f0; | |
| } | |
| .btn-secondary:hover { | |
| background: #edf2f7; | |
| transform: translateY(-1px); | |
| } | |
| /* Efectos de animación para el formulario */ | |
| .newpost-container { | |
| animation: fadeInUp 0.6s ease-out; | |
| } | |
| @keyframes fadeInUp { | |
| from { | |
| opacity: 0; | |
| transform: translateY(30px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| .form-group { | |
| animation: slideIn 0.4s ease-out; | |
| } | |
| @keyframes slideIn { | |
| from { | |
| opacity: 0; | |
| transform: translateX(-20px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateX(0); | |
| } | |
| } | |
| /* Responsive design */ | |
| @media (max-width: 768px) { | |
| .newpost-container { | |
| padding: 1.5rem; | |
| margin: 1rem; | |
| } | |
| .form-row { | |
| grid-template-columns: 1fr; | |
| } | |
| .form-actions { | |
| flex-direction: column; | |
| } | |
| .app-title { | |
| font-size: 2rem; | |
| } | |
| .newpost-header h1 { | |
| font-size: 1.8rem; | |
| } | |
| } | |
| @media (max-width: 480px) { | |
| .newpost-container { | |
| padding: 1rem; | |
| margin: 0.5rem; | |
| } | |
| .app-title { | |
| font-size: 1.5rem; | |
| } | |
| .newpost-header h1 { | |
| font-size: 1.5rem; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import './NewPost.css' | |
| const NewPost = () => { | |
| const onSubmit = async (data) => { | |
| try { | |
| // Simular envío de datos | |
| await new Promise(resolve => setTimeout(resolve, 1000)) | |
| console.log('Datos del post:', data) | |
| alert('¡Post creado exitosamente!') | |
| // TODO: Añadir reset | |
| } catch (error) { | |
| console.error('Error al crear el post:', error) | |
| alert('Error al crear el post. Intenta nuevamente.') | |
| } | |
| } | |
| const categories = [ | |
| 'Tecnología', | |
| 'Programación', | |
| 'Diseño', | |
| 'Marketing', | |
| 'Negocios', | |
| 'Educación', | |
| 'Estilo de vida', | |
| 'Salud', | |
| 'Viajes' | |
| ] | |
| return ( | |
| <div className='newpost-container'> | |
| <div className='newpost-header'> | |
| <h1>Crear Nueva Entrada</h1> | |
| <p>Comparte tus ideas con el mundo</p> | |
| </div> | |
| <div className='newpost-form'> | |
| <div className='form-group'> | |
| <label htmlFor='title' className='form-label'> | |
| Título del Post * | |
| </label> | |
| <input | |
| type='text' | |
| id='title' | |
| className='form-input' // TODO: Añadir clase de error si hay errores | |
| placeholder='Ingresa un título para tu post' | |
| // TODO: Registrar input title | |
| /> | |
| {/* TODO: Mostrar mensaje de error */} | |
| </div> | |
| <div className='form-group'> | |
| <label htmlFor='content' className='form-label'> | |
| Contenido * | |
| </label> | |
| <textarea | |
| id='content' | |
| rows='6' | |
| className='form-textarea' // TODO: Añadir clase de error si hay | |
| placeholder='Escribe el contenido de tu post aquí...' | |
| // TODO: Registrar input content | |
| /> | |
| {/* TODO: Mostrar mensaje de error */} | |
| </div> | |
| <div className='form-row'> | |
| <div className='form-group'> | |
| <label htmlFor='category' className='form-label'> | |
| Categoría * | |
| </label> | |
| <select | |
| id='category' | |
| className='form-select ' // TODO: Añadir clase de error si hay | |
| // TODO: Registrar input category | |
| > | |
| <option value=''>Selecciona una categoría</option> | |
| {categories.map((category) => ( | |
| <option key={category} value={category}> | |
| {category} | |
| </option> | |
| ))} | |
| </select> | |
| {/* TODO: Mostrar mensaje de error */} | |
| </div> | |
| <div className='form-group'> | |
| <label htmlFor='author' className='form-label'> | |
| Autor * | |
| </label> | |
| <input | |
| type='text' | |
| id='author' | |
| className='form-input ' // TODO: Añadir clase de error si hay | |
| placeholder='Tu nombre' | |
| // TODO: Registrar input author | |
| /> | |
| {/* TODO: Mostrar mensaje de error */} | |
| </div> | |
| </div> | |
| <div className='form-group'> | |
| <label htmlFor='publishDate' className='form-label'> | |
| Fecha de Publicación * | |
| </label> | |
| <input | |
| type='datetime-local' | |
| id='publishDate' | |
| className='form-input ' // TODO: Añadir clase de error si hay | |
| // TODO: Registrar input publishDate | |
| /> | |
| {/* TODO: Mostrar mensaje de error */} | |
| </div> | |
| <div className='form-actions'> | |
| <button | |
| type='button' | |
| className='btn btn-secondary' | |
| onClick={() => {}} // TODO: Añadir reset del formulario | |
| > | |
| Limpiar | |
| </button> | |
| <button | |
| type='button' | |
| className='btn btn-primary' | |
| // TODO: Añadir lógica para deshabilitar si se esta enviando el formulario. | |
| onClick={onSubmit} // TODO: Actualizar función de envío | |
| > | |
| {/* TODO: Añadir texto condicional al botón */} | |
| Publicar Post | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| ) | |
| } | |
| export default NewPost |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment