Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions Dockerfile.backend
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
FROM python:3.9-slim-buster
FROM python:3.11-slim-bookworm

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends
build-essential
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libpq-dev

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY src/ /app/src
COPY wsgi.py .

EXPOSE 8000

Expand Down
2 changes: 2 additions & 0 deletions Dockerfile.frontend
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ FROM node:20-alpine AS builder
WORKDIR /app

COPY package.json package-lock.json vite.config.js ./
COPY index.html .

RUN npm install

COPY src/front/ ./src/front/
Expand Down
6 changes: 2 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
version: '3.8'

services:
# Servicio del Backend (Python/Flask API)
server:
build:
context: . # El contexto es la raíz, donde están todos los archivos
context: . # El contexto es la raíz, donde están todos los archivos
dockerfile: Dockerfile.backend # Especifica qué Dockerfile usar
restart: always
env_file: ./.env
Expand Down Expand Up @@ -54,4 +52,4 @@ networks:

volumes:
postgres-data:
driver: local
driver: local
23 changes: 0 additions & 23 deletions src/front/components/BackendURL.jsx

This file was deleted.

280 changes: 140 additions & 140 deletions src/front/components/HeaderContact.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,164 +61,164 @@ const HeaderContact = () => {

return (
<>
<section className="header w-100 h-100 position-relative ">
<img
src={HomeContact}
alt="CloudTech background image"
className="z-n1 mx-auto position-absolute w-100 h-100 object-fit-cover d-sm-block mb-5" />

<div className="position-absolute w-100 h-100 bg-dark bg-opacity-50 mx-auto"></div>
<div className="container w-100 h-100 py-2">
<div className="row align-items-center justify-content-center justify-content-lg-end mb-5">
<div className="col-12 col-lg-6 z-1 align-items-center pt-5 mt-5 pt-lg-0 mt-lg-3">
<h1 className="hero-title-home display-4 fw-bolder w-100 mt-2 text-lg-center text-center d-none d-lg-block">
{t('contact.sectionTitle')}
</h1>

<h1 className="hero-title-home display-4 fw-bolder w-100 mt-5 text-center d-lg-none">
{t('contact.sectionTitle')}
</h1>

<p className="hero-subtitle-home fs-5 text-white fw-bold w-100 mb-4 d-none d-lg-block text-lg-center">
{t('contact.sectionDescription')}
</p>

<p className="hero-subtitle-home fs-5 text-white fw-bold w-100 mb-4 text-center d-lg-none">
{t('contact.sectionDescription')}
</p>

<form onSubmit={handleSubmit} noValidate className="text-start">
<div className="mb-3">
<label htmlFor="name" className="form-label fw-bold form-label-contact">
{t('contact.labels.nameLabel')}
</label>

<input
type="text"
className={`form-control rounded-3 ${status === 'error' && error?.name ? 'is-invalid' : ''}`}
id="name" name="name" value={formData.name} onChange={handleChange}
placeholder={t('contact.placeholders.nameHolder')}
required
/>
{status === 'error' && error?.name && <div className="invalid-feedback fw-bold">{error.name}</div>}
</div>

<div className="row mb-3">
<div className="col-6">
<label
htmlFor="phone"
className="form-label fw-bold form-label-contact">
{t('contact.labels.phoneLabel')}
<section className="header w-100 h-100 position-relative ">
<img
src={HomeContact}
alt="CloudTech background image"
className="z-n1 mx-auto position-absolute w-100 h-100 object-fit-cover d-sm-block mb-5" />

<div className="position-absolute w-100 h-100 bg-dark bg-opacity-50 mx-auto"></div>
<div className="container w-100 h-100 py-2">
<div className="row align-items-center justify-content-center justify-content-lg-end mb-5">
<div className="col-12 col-lg-6 z-1 align-items-center pt-5 mt-5 pt-lg-0 mt-lg-3">
<h1 className="hero-title-home display-4 fw-bolder w-100 mt-2 text-lg-center text-center d-none d-lg-block">
{t('contact.sectionTitle')}
</h1>

<h1 className="hero-title-home display-4 fw-bolder w-100 mt-5 text-center d-lg-none">
{t('contact.sectionTitle')}
</h1>

<p className="hero-subtitle-home fs-5 text-white fw-bold w-100 mb-4 d-none d-lg-block text-lg-center">
{t('contact.sectionDescription')}
</p>

<p className="hero-subtitle-home fs-5 text-white fw-bold w-100 mb-4 text-center d-lg-none">
{t('contact.sectionDescription')}
</p>

<form onSubmit={handleSubmit} noValidate className="text-start">
<div className="mb-3">
<label htmlFor="name" className="form-label fw-bold form-label-contact">
{t('contact.labels.nameLabel')}
</label>

<input
type="tel"
className={`form-control rounded-3 ${status === 'error' && error?.phone ? 'is-invalid' : ''}`}
id="phone" name="phone"
value={formData.phone}
onChange={handleChange}
placeholder={t('contact.placeholders.phoneHolder')}
type="text"
className={`form-control rounded-3 ${status === 'error' && error?.name ? 'is-invalid' : ''}`}
id="name" name="name" value={formData.name} onChange={handleChange}
placeholder={t('contact.placeholders.nameHolder')}
required
/>
{status === 'error' && error?.name && <div className="invalid-feedback fw-bold">{error.name}</div>}
</div>

{status === 'error' && error?.phone &&
<div className="invalid-feedback fw-bold">{error.phone}</div>}
<div className="row mb-3">
<div className="col-6">
<label
htmlFor="phone"
className="form-label fw-bold form-label-contact">
{t('contact.labels.phoneLabel')}
</label>

<input
type="tel"
className={`form-control rounded-3 ${status === 'error' && error?.phone ? 'is-invalid' : ''}`}
id="phone" name="phone"
value={formData.phone}
onChange={handleChange}
placeholder={t('contact.placeholders.phoneHolder')}
required
/>

{status === 'error' && error?.phone &&
<div className="invalid-feedback fw-bold">{error.phone}</div>}
</div>

<div className="col-6">
<label htmlFor="email" className="form-label fw-bold form-label-contact">
{t('contact.labels.emailLabel')}
</label>

<input
type="email"
className={`form-control rounded-3 ${status === 'error' && error?.email ? 'is-invalid' : ''}`}
id="email" name="email"
value={formData.email}
onChange={handleChange}
placeholder={t('contact.placeholders.emailHolder')}
required
/>

{status === 'error' && error?.email &&
<div className="invalid-feedback fw-bold">{error.email}</div>}
</div>
</div>

<div className="col-6">
<label htmlFor="email" className="form-label fw-bold form-label-contact">
{t('contact.labels.emailLabel')}
<div className="mb-3">
<label
htmlFor="company"
className="form-label fw-bold form-label-contact">
{t('contact.labels.projectNameLabel')}
</label>

<input
type="email"
className={`form-control rounded-3 ${status === 'error' && error?.email ? 'is-invalid' : ''}`}
id="email" name="email"
value={formData.email}
type="text"
className="form-control rounded-3"
id="company" name="company"
value={formData.company}
onChange={handleChange}
placeholder={t('contact.placeholders.emailHolder')}
required
placeholder={t('contact.placeholders.projectHolder')}
/>
</div>

<div className="mb-4">
<label
htmlFor="message"
className="form-label fw-bold form-label-contact">
{t('contact.labels.messageLabel')}
</label>

<textarea
className="form-control textarea-contact rounded-3"
id="message"
name="message"
rows="4"
value={formData.message}
onChange={handleChange}
placeholder={t('contact.placeholders.messageHolder')}
>
</textarea>
</div>

{status === 'error' && error?.email &&
<div className="invalid-feedback fw-bold">{error.email}</div>}
{status === 'success' &&
<div className="alert alert-success">
{t('contact.alerts.alertSuccess')}
</div>}

{status === 'error' && error?.general &&
<div className="alert alert-danger">
{t('contact.alerts.alertError')}
</div>}


<div className="d-flex flex-column flex-lg-row gap-3">
<button
type="submit"
className="btn btn-submit-contact fw-semibold btn-lg rounded-pill px-5"
disabled={status === 'loading'}
>
{status === 'loading' ? `${t('contact.alerts.loading')}` : `${t('contact.formButton')}`}
</button>
<a
href="https://wa.me/593978879838"
target="_blank"
rel="noopener noreferrer"
className="btn btn-outline btn-lg rounded-pill px-5 w-100"
>
{t('contact.whatsAppButton')} <FontAwesomeIcon icon={faWhatsapp} />
</a>
</div>
</div>

<div className="mb-3">
<label
htmlFor="company"
className="form-label fw-bold form-label-contact">
{t('contact.labels.projectNameLabel')}
</label>

<input
type="text"
className="form-control rounded-3"
id="company" name="company"
value={formData.company}
onChange={handleChange}
placeholder={t('contact.placeholders.projectHolder')}
/>
</div>

<div className="mb-4">
<label
htmlFor="message"
className="form-label fw-bold form-label-contact">
{t('contact.labels.messageLabel')}
</label>

<textarea
className="form-control textarea-contact rounded-3"
id="message"
name="message"
rows="4"
value={formData.message}
onChange={handleChange}
placeholder={t('contact.placeholders.messageHolder')}
>
</textarea>
</div>

{status === 'success' &&
<div className="alert alert-success">
{t('contact.alerts.alertSuccess')}
</div>}

{status === 'error' && error?.general &&
<div className="alert alert-danger">
{t('contact.alerts.alertError')}
</div>}


<div className="d-flex flex-column flex-lg-row gap-3">
<button
type="submit"
className="btn btn-submit-contact fw-semibold btn-lg rounded-pill px-5"
disabled={status === 'loading'}
>
{status === 'loading' ? `${t('contact.alerts.loading')}` : `${t('contact.formButton')}`}
</button>
<a
href="https://wa.me/593978879838"
target="_blank"
rel="noopener noreferrer"
className="btn btn-outline btn-lg rounded-pill px-5 w-100"
>
{t('contact.whatsAppButton')} <FontAwesomeIcon icon={faWhatsapp} />
</a>
</div>
</form>
</form>

</div>
</div>
</div>
</div>
</section>
<div className="h-100 mb-4">
<br />
</div>
</section>
<div className="h-100 mb-4">
<br/>
</div>
</>
</>
);
};

Expand Down
Loading