WIP
This commit is contained in:
115
src/app/registration/registration.component.html
Normal file
115
src/app/registration/registration.component.html
Normal file
@@ -0,0 +1,115 @@
|
||||
<div class="registration-container">
|
||||
<h2 class="title">🚀 Spaceflight Candidate Registration</h2>
|
||||
|
||||
<form [formGroup]="form" (ngSubmit)="onSubmit()" class="form">
|
||||
<!-- <div class="upload-section">
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
(change)="onFileSelected($event)"
|
||||
/>
|
||||
<mat-label>Candidate Profile Picture</mat-label>
|
||||
<div class="preview">
|
||||
<img [src]="previewUrl" alt="Preview" />
|
||||
</div>
|
||||
</div> -->
|
||||
<app-image-input></app-image-input>
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Full Name</mat-label>
|
||||
<input matInput formControlName="fullName" />
|
||||
@if (form.get('fullName')?.hasError('required')) {
|
||||
<mat-error>
|
||||
Name is required
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Email</mat-label>
|
||||
<input matInput formControlName="email" />
|
||||
@if (form.get('email')?.hasError('email')) {
|
||||
<mat-error>
|
||||
Invalid email
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Phone Number</mat-label>
|
||||
<input matInput formControlName="phone" placeholder="+972-XXXXXXX"/>
|
||||
@if (form.get('phone')?.hasError('required')) {
|
||||
<mat-error>
|
||||
Phone number is required
|
||||
</mat-error>
|
||||
}
|
||||
@if (form.get('phone')?.hasError('pattern')){
|
||||
<mat-error>
|
||||
Invalid phone number
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Age</mat-label>
|
||||
<input matInput type="number" formControlName="age" />
|
||||
@if (form.get('age')?.hasError('min') || form.get('age')?.hasError('max')) {
|
||||
<mat-error>
|
||||
Only aplicants of age 18 - 70 allowed
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>City / Region</mat-label>
|
||||
<input matInput formControlName="city" />
|
||||
@if (form.get('city')?.hasError('required')) {
|
||||
<mat-error>
|
||||
Field is required
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Hobbies</mat-label>
|
||||
<textarea matInput rows="2" formControlName="hobbies"></textarea>
|
||||
@if (form.get('hobbies')?.hasError('maxLength')) {
|
||||
<mat-error>
|
||||
Maximum length is 300 characters
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Why I am the perfect candidate</mat-label>
|
||||
<textarea matInput rows="4" formControlName="reason"></textarea>
|
||||
@if (form.get('reason')?.hasError('required')) {
|
||||
<mat-error>
|
||||
Field is required
|
||||
</mat-error>
|
||||
}
|
||||
@if (form.get('reason')?.hasError('maxLength')) {
|
||||
<mat-error>
|
||||
Maximum length is 300 characters
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
class="full-width"
|
||||
type="submit"
|
||||
[disabled]="form.invalid"
|
||||
>
|
||||
Submit Application
|
||||
</button>
|
||||
|
||||
<button
|
||||
mat-raised-button
|
||||
(click)="onCheckErrors()">
|
||||
check
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
164
src/app/registration/registration.component.scss
Normal file
164
src/app/registration/registration.component.scss
Normal file
@@ -0,0 +1,164 @@
|
||||
/* Cosmic-themed container styling */
|
||||
.registration-container {
|
||||
max-width: 900px;
|
||||
margin: 2rem auto;
|
||||
padding: 2.5rem;
|
||||
background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%);
|
||||
color: #e0e0e0;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Cosmic background overlay */
|
||||
.registration-container::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 70%);
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Form title with space theme */
|
||||
.title {
|
||||
text-align: center;
|
||||
font-size: 2.2rem;
|
||||
font-weight: 700;
|
||||
color: #00d4ff;
|
||||
margin-bottom: 2.5rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 3px;
|
||||
text-shadow: 0 0 12px rgba(0, 212, 255, 0.6);
|
||||
animation: glow 2s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
/* Glowing title animation */
|
||||
@keyframes glow {
|
||||
from {
|
||||
text-shadow: 0 0 8px rgba(0, 212, 255, 0.4);
|
||||
}
|
||||
to {
|
||||
text-shadow: 0 0 16px rgba(0, 212, 255, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
/* Form styling */
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
/* Full-width form fields */
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// /* Material form field customization */
|
||||
// ::ng-deep .mat-form-field {
|
||||
// .mat-form-field-label {
|
||||
// color: #b0bec5;
|
||||
// font-weight: 500;
|
||||
// }
|
||||
|
||||
// .mat-form-field-underline {
|
||||
// background-color: #00d4ff !important;
|
||||
// }
|
||||
|
||||
// .mat-form-field-ripple {
|
||||
// background-color: #00d4ff !important;
|
||||
// }
|
||||
|
||||
// input, textarea {
|
||||
// color: #e0e0e0;
|
||||
// background-color: rgba(255, 255, 255, 0.08);
|
||||
// border-radius: 6px;
|
||||
// padding: 0.75rem;
|
||||
// transition: background-color 0.3s ease;
|
||||
// }
|
||||
|
||||
// input:focus, textarea:focus {
|
||||
// background-color: rgba(255, 255, 255, 0.12);
|
||||
// }
|
||||
|
||||
// textarea {
|
||||
// resize: vertical;
|
||||
// min-height: 80px;
|
||||
// }
|
||||
// }
|
||||
|
||||
/* Error message styling */
|
||||
// ::ng-deep .mat-error {
|
||||
// color: #ff6b6b;
|
||||
// font-size: 0.9rem;
|
||||
// }
|
||||
|
||||
/* Upload section */
|
||||
.upload-section {
|
||||
align-items: center;
|
||||
margin: 2rem 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
|
||||
.preview {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
border: 4px solid #00d4ff;
|
||||
box-shadow: 0 0 20px rgba(0, 212, 255, 0.4);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
img:hover {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 0 25px rgba(0, 212, 255, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive design */
|
||||
@media (max-width: 768px) {
|
||||
.registration-container {
|
||||
margin: 1.5rem;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.8rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.upload-section img {
|
||||
max-width: 140px;
|
||||
}
|
||||
|
||||
// ::ng-deep .mat-raised-button {
|
||||
// padding: 0.75rem 1.5rem;
|
||||
// font-size: 0.95rem;
|
||||
// }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.registration-container {
|
||||
margin: 1rem;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.4rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.upload-section img {
|
||||
max-width: 120px;
|
||||
}
|
||||
|
||||
}
|
||||
86
src/app/registration/registration.component.ts
Normal file
86
src/app/registration/registration.component.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { ImageInputComponent } from "../image-input/image-input.component";
|
||||
|
||||
const israeliPhoneRegex = /^(?:(?:(\+?972|\(\+?972\)|\+?\(972\))(?:\s|\.|-)?([1-9]\d?))|(0[23489]{1})|(0[57]{1}[0-9]))(?:\s|\.|-)?([^0\D]{1}\d{2}(?:\s|\.|-)?\d{4})$/;
|
||||
@Component({
|
||||
selector: 'app-registration',
|
||||
imports: [
|
||||
CommonModule,
|
||||
ReactiveFormsModule,
|
||||
MatInputModule,
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatFormFieldModule,
|
||||
ImageInputComponent
|
||||
],
|
||||
templateUrl: './registration.component.html',
|
||||
styleUrls: ['./registration.component.scss'],
|
||||
})
|
||||
export class RegistrationComponent implements OnInit {
|
||||
|
||||
fb = inject(FormBuilder);
|
||||
previewUrl: string | ArrayBuffer | null = null;
|
||||
|
||||
form = this.fb.group({
|
||||
fullName: ['', [Validators.required, Validators.minLength(3)]],
|
||||
email: ['', [Validators.required, Validators.email]],
|
||||
phone: ['', [Validators.required, Validators.pattern(israeliPhoneRegex)]],
|
||||
age: [0, [Validators.required, Validators.min(18), Validators.max(70)]],
|
||||
city: ['', Validators.required],
|
||||
hobbies: ['', [Validators.maxLength(300)]],
|
||||
reason: ['', [Validators.required, Validators.maxLength(300)]],
|
||||
profileImage: this.fb.control<string | null>(null, Validators.required),
|
||||
});
|
||||
|
||||
ngOnInit(): void {
|
||||
const savedData = localStorage.getItem('registration');
|
||||
if (!savedData) return;
|
||||
|
||||
const parsed = JSON.parse(savedData);
|
||||
const dayMilliseconds = 1000 * 60 * 60 * 24;
|
||||
if (Date.now() - parsed.timestamp < dayMilliseconds * 3) {
|
||||
this.form.patchValue(parsed.data);
|
||||
this.previewUrl = parsed.data.profileImage;
|
||||
} else {
|
||||
localStorage.removeItem('registration');
|
||||
}
|
||||
}
|
||||
|
||||
onFileSelected(event: any) {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
if (typeof reader.result === 'string') {
|
||||
this.previewUrl = reader.result;
|
||||
this.form.patchValue({ profileImage: reader.result });
|
||||
}
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
if (this.form.valid) {
|
||||
localStorage.setItem(
|
||||
'registration',
|
||||
JSON.stringify({
|
||||
data: this.form.value,
|
||||
timestamp: Date.now(),
|
||||
})
|
||||
);
|
||||
alert('✅ Application saved! You can re-edit within 3 days.');
|
||||
}
|
||||
}
|
||||
|
||||
onCheckErrors() {
|
||||
console.log(this.form.controls.age.errors);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user