fix(deploy): fixed deploy for gradle.
Some checks failed
Build, Test and Deploy / test-backend (push) Failing after 3s
Build, Test and Deploy / build-and-push (push) Has been skipped
Build, Test and Deploy / deploy (push) Has been skipped

This commit is contained in:
2026-02-04 15:33:28 +01:00
parent 2f7e8798d2
commit db4df2573c
7 changed files with 84 additions and 36 deletions

View File

@@ -21,13 +21,11 @@ jobs:
java-version: '21'
distribution: 'temurin'
- name: Run Tests with Maven
- name: Run Tests with Gradle
run: |
echo "Installing Maven..."
apt-get update && apt-get install -y maven
echo "Starting Maven Build..."
cd backend
mvn -B test
chmod +x gradlew
./gradlew test
build-and-push:
needs: test-backend

View File

@@ -1,11 +1,12 @@
# Stage 1: Build Java JAR
FROM maven:3.9-eclipse-temurin-21 AS build
FROM eclipse-temurin:21-jdk-jammy AS build
WORKDIR /app
COPY pom.xml .
COPY gradle gradle
COPY gradlew build.gradle settings.gradle ./
# Download dependencies first to cache them
RUN mvn dependency:go-offline
RUN ./gradlew dependencies --no-daemon
COPY src ./src
RUN mvn clean package -DskipTests
RUN ./gradlew bootJar -x test --no-daemon
# Stage 2: Runtime Environment
FROM eclipse-temurin:21-jre-jammy
@@ -34,7 +35,7 @@ ENV SLICER_PATH="/opt/orcaslicer/AppRun"
WORKDIR /app
# Copy JAR from build stage
COPY --from=build /app/target/*.jar app.jar
COPY --from=build /app/build/libs/*.jar app.jar
# Copy profiles
COPY profiles ./profiles

View File

@@ -106,7 +106,7 @@ export class QuoteEstimatorService {
return {
price: Math.round(totalPrice * 100) / 100,
currency: 'EUR',
currency: 'CHF',
printTimeHours: Math.ceil(totalTime / 3600), // Ceil hours
materialUsageGrams: Math.ceil(totalWeight),
setupCost

View File

@@ -28,22 +28,27 @@ interface FilePreview {
</div>
<div class="row">
<!-- Email -->
<!-- Phone -->
<app-input formControlName="email" type="email" label="Email *" placeholder="tuo@email.com" class="col"></app-input>
<!-- Phone -->
<app-input formControlName="phone" type="tel" [label]="('CONTACT.PHONE' | translate)" placeholder="+39 000 000 0000" class="col"></app-input>
<app-input formControlName="phone" type="tel" [label]="('CONTACT.PHONE' | translate)" placeholder="+41 00 000 00 00" class="col"></app-input>
</div>
<!-- Name (Always Required) -->
<app-input formControlName="name" label="Nome *" placeholder="Il tuo nome"></app-input>
<!-- Company Toggle & Fields -->
<div class="form-group checkbox-group">
<input type="checkbox" formControlName="isCompany" id="isCompany">
<label for="isCompany">{{ 'CONTACT.IS_COMPANY' | translate }}</label>
<!-- User Type Selector (Segmented Control) -->
<div class="user-type-selector">
<div class="type-option" [class.selected]="!isCompany" (click)="setCompanyMode(false)">
{{ 'CONTACT.TYPE_PRIVATE' | translate }}
</div>
<div class="type-option" [class.selected]="isCompany" (click)="setCompanyMode(true)">
{{ 'CONTACT.TYPE_COMPANY' | translate }}
</div>
</div>
<div *ngIf="form.get('isCompany')?.value" class="company-fields">
<!-- Personal Name (Only if NOT Company) -->
<app-input *ngIf="!isCompany" formControlName="name" label="Nome *" placeholder="Il tuo nome"></app-input>
<!-- Company Fields (Only if Company) -->
<div *ngIf="isCompany" class="company-fields">
<app-input formControlName="companyName" [label]="('CONTACT.COMPANY_NAME' | translate) + ' *'" placeholder="Nome Azienda"></app-input>
<app-input formControlName="referencePerson" [label]="('CONTACT.REF_PERSON' | translate) + ' *'" placeholder="Persona di Riferimento"></app-input>
</div>
@@ -114,32 +119,54 @@ interface FilePreview {
flex-direction: column;
gap: var(--space-4);
margin-bottom: var(--space-4);
@media(min-width: 768px) {
flex-direction: row;
.col { flex: 1; margin-bottom: 0; }
}
}
/* Modify direct app-input child of row if possible or target host */
app-input.col {
width: 100%;
}
app-input.col { width: 100%; }
.checkbox-group {
flex-direction: row;
align-items: center;
gap: var(--space-2);
input[type="checkbox"] { width: auto; margin: 0; }
label { margin: 0; }
/* User Type Selector Styles */
.user-type-selector {
display: inline-flex;
background-color: var(--color-neutral-100);
border-radius: var(--radius-md);
padding: 4px;
margin-bottom: var(--space-4);
gap: 4px;
}
.type-option {
padding: 8px 16px;
border-radius: var(--radius-sm);
cursor: pointer;
font-size: 0.875rem;
font-weight: 500;
color: var(--color-text-muted);
transition: all 0.2s ease;
user-select: none;
&:hover { color: var(--color-text); }
&.selected {
background-color: var(--color-brand);
color: #000; /* Assuming brand color is light/yellow, black text is safer. Adjust if brand is dark. */
font-weight: 600;
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}
}
.company-fields {
display: flex;
flex-direction: column;
gap: var(--space-4);
padding-left: var(--space-4);
border-left: 2px solid var(--color-border);
margin-bottom: var(--space-4);
}
/* File Upload Styles */
.drop-zone {
border: 2px dashed var(--color-border);
border-radius: var(--radius-md);
@@ -200,6 +227,10 @@ export class ContactFormComponent {
sent = signal(false);
files = signal<FilePreview[]>([]);
get isCompany(): boolean {
return this.form.get('isCompany')?.value;
}
requestTypes = [
{ value: 'custom', label: 'CONTACT.REQ_TYPE_CUSTOM' },
{ value: 'series', label: 'CONTACT.REQ_TYPE_SERIES' },
@@ -221,21 +252,35 @@ export class ContactFormComponent {
// Handle conditional validation for Company fields
this.form.get('isCompany')?.valueChanges.subscribe(isCompany => {
const nameControl = this.form.get('name');
const companyNameControl = this.form.get('companyName');
const refPersonControl = this.form.get('referencePerson');
if (isCompany) {
// Company Mode: Name not required / cleared, Company defaults required
nameControl?.clearValidators();
nameControl?.setValue(''); // Optional: clear value
companyNameControl?.setValidators([Validators.required]);
refPersonControl?.setValidators([Validators.required]);
} else {
// Private Mode: Name required
nameControl?.setValidators([Validators.required]);
companyNameControl?.clearValidators();
refPersonControl?.clearValidators();
}
nameControl?.updateValueAndValidity();
companyNameControl?.updateValueAndValidity();
refPersonControl?.updateValueAndValidity();
});
}
setCompanyMode(isCompany: boolean) {
this.form.patchValue({ isCompany });
}
onFileSelected(event: Event) {
const input = event.target as HTMLInputElement;
if (input.files) this.handleFiles(Array.from(input.files));

View File

@@ -24,7 +24,7 @@ import { AppCardComponent } from '../../shared/components/app-card/app-card.comp
`,
styles: [`
.contact-hero {
padding: 5rem 0 3.5rem;
padding: 3rem 0 2rem;
background: var(--color-bg);
text-align: center;
}
@@ -34,7 +34,7 @@ import { AppCardComponent } from '../../shared/components/app-card/app-card.comp
margin: var(--space-3) auto 0;
}
.content {
padding: 3rem 0 5rem;
padding: 2rem 0 5rem;
max-width: 800px;
}
`]

View File

@@ -40,7 +40,7 @@
},
"SHOP": {
"TITLE": "Technical solutions",
"SUBTITLE": "Ready-made products solving practical problems, no useless decorations.",
"SUBTITLE": "Ready-made products solving practical problems",
"ADD_CART": "Add to Cart",
"BACK": "Back to Shop"
},
@@ -66,6 +66,8 @@
"TITLE": "Contact Us",
"SEND": "Send Message",
"REQ_TYPE_LABEL": "Type of Request",
"TYPE_PRIVATE": "Private",
"TYPE_COMPANY": "Business",
"REQ_TYPE_CUSTOM": "Custom Quote",
"REQ_TYPE_SERIES": "Series Production",
"REQ_TYPE_CONSULT": "Consultation",

View File

@@ -45,7 +45,7 @@
},
"SHOP": {
"TITLE": "Soluzioni tecniche",
"SUBTITLE": "Prodotti pronti che risolvono problemi pratici, niente decorazioni inutili.",
"SUBTITLE": "Prodotti pronti che risolvono problemi pratici",
"ADD_CART": "Aggiungi al Carrello",
"BACK": "Torna allo Shop"
},
@@ -71,6 +71,8 @@
"TITLE": "Contattaci",
"SEND": "Invia Messaggio",
"REQ_TYPE_LABEL": "Tipo di Richiesta",
"TYPE_PRIVATE": "Privato",
"TYPE_COMPANY": "Azienda",
"REQ_TYPE_CUSTOM": "Preventivo Personalizzato",
"REQ_TYPE_SERIES": "Stampa in Serie",
"REQ_TYPE_CONSULT": "Consulenza",