005
This commit is contained in:
0
src/templates/first_name.html
Normal file
0
src/templates/first_name.html
Normal file
253
src/templates/index.html
Normal file
253
src/templates/index.html
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Flight Booking</title>
|
||||||
|
<style>
|
||||||
|
/* Reset and Base Styles */
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Container */
|
||||||
|
.container {
|
||||||
|
width: 90%;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
.header {
|
||||||
|
background-color: #2c3e50;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flight Search Form */
|
||||||
|
.flight-search {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 30px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input,
|
||||||
|
.form-group select {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #3498db;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn:hover {
|
||||||
|
background-color: #2980b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flight Results */
|
||||||
|
.flight-results {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flight-card {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flight-details {
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flight-price {
|
||||||
|
flex: 1;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flight-price .price {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #2ecc71;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-btn {
|
||||||
|
background-color: #2ecc71;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-btn:hover {
|
||||||
|
background-color: #27ae60;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Design */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.form-row {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flight-card {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flight-price {
|
||||||
|
margin-top: 15px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<header class="header">
|
||||||
|
<h1>Flight Booking</h1>
|
||||||
|
<p>Find and book your perfect flight</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="flight-search">
|
||||||
|
<form id="flight-search-form">
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="from">From</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="from"
|
||||||
|
name="from"
|
||||||
|
placeholder="Departure City"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="to">To</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="to"
|
||||||
|
name="to"
|
||||||
|
placeholder="Arrival City"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="departure-date">Departure Date</label>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
id="departure-date"
|
||||||
|
name="departure-date"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="passengers">Passengers</label>
|
||||||
|
<select id="passengers" name="passengers">
|
||||||
|
<option value="1">1 Passenger</option>
|
||||||
|
<option value="2">2 Passengers</option>
|
||||||
|
<option value="3">3 Passengers</option>
|
||||||
|
<option value="4">4 Passengers</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="search-btn">
|
||||||
|
Search Flights
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="flight-results">
|
||||||
|
<div class="flight-card">
|
||||||
|
<div class="flight-details">
|
||||||
|
<h3>New York (JFK) to Los Angeles (LAX)</h3>
|
||||||
|
<p>Departure: June 15, 2024 at 08:00 AM</p>
|
||||||
|
<p>Airline: Delta Air Lines</p>
|
||||||
|
<p>Flight Duration: 6h 15m</p>
|
||||||
|
</div>
|
||||||
|
<div class="flight-price">
|
||||||
|
<span class="price">$345.99</span>
|
||||||
|
<button class="book-btn">Book Now</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flight-card">
|
||||||
|
<div class="flight-details">
|
||||||
|
<h3>Chicago (ORD) to San Francisco (SFO)</h3>
|
||||||
|
<p>Departure: June 16, 2024 at 11:30 AM</p>
|
||||||
|
<p>Airline: United Airlines</p>
|
||||||
|
<p>Flight Duration: 4h 45m</p>
|
||||||
|
</div>
|
||||||
|
<div class="flight-price">
|
||||||
|
<span class="price">$289.50</span>
|
||||||
|
<button class="book-btn">Book Now</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
371
src/templates/signup.html
Normal file
371
src/templates/signup.html
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>User Registration</title>
|
||||||
|
<style>
|
||||||
|
/* Reset and Base Styles */
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Container */
|
||||||
|
.container {
|
||||||
|
width: 90%;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
.header {
|
||||||
|
background-color: #2c3e50;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Registration Form */
|
||||||
|
.registration-form {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input,
|
||||||
|
.form-group select {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row .form-group {
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row .form-group:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-btn {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #3498db;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-btn:hover {
|
||||||
|
background-color: #2980b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gender Radio Buttons */
|
||||||
|
.gender-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gender-group .form-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gender-group input[type="radio"] {
|
||||||
|
margin-right: 5px;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Design */
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.form-row {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row .form-group {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error Handling */
|
||||||
|
.error-message {
|
||||||
|
color: #e74c3c;
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin-top: 5px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<header class="header">
|
||||||
|
<h1>User Registration</h1>
|
||||||
|
<p>Create your account to start booking flights</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="registration-form">
|
||||||
|
<form id="user-registration-form">
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="first-name">First Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="first-name"
|
||||||
|
name="first_name"
|
||||||
|
placeholder="Enter your first name"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<div class="error-message" id="first-name-error">
|
||||||
|
Please enter a valid first name
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="form-group"
|
||||||
|
hx-target="this"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
>
|
||||||
|
<label for="last-name">Last Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="last-name"
|
||||||
|
name="last_name"
|
||||||
|
placeholder="Enter your last name"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<div class="error-message" id="last-name-error">
|
||||||
|
Please enter a valid last name
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">Email Address</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
id="email"
|
||||||
|
name="email"
|
||||||
|
placeholder="Enter your email"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<div class="error-message" id="email-error">
|
||||||
|
Please enter a valid email address
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
id="password"
|
||||||
|
name="password"
|
||||||
|
placeholder="Create a strong password"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<div class="error-message" id="password-error">
|
||||||
|
Password must be at least 8 characters long
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<!-- <div class="form-group">
|
||||||
|
<label for="date-of-birth">Date of Birth</label>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
id="date-of-birth"
|
||||||
|
name="date-of-birth"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<div class="error-message" id="dob-error">
|
||||||
|
You must be at least 18 years old
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Gender</label>
|
||||||
|
<div class="gender-group">
|
||||||
|
<div class="form-group">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
id="male"
|
||||||
|
name="gender"
|
||||||
|
value="male"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<label for="male">Male</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
id="female"
|
||||||
|
name="gender"
|
||||||
|
value="female"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<label for="female">Female</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
id="other"
|
||||||
|
name="gender"
|
||||||
|
value="other"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<label for="other">Other</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <div class="form-group">
|
||||||
|
<label for="country">Country</label>
|
||||||
|
<select id="country" name="country" required>
|
||||||
|
<option value="">Select your country</option>
|
||||||
|
<option value="us">United States</option>
|
||||||
|
<option value="ca">Canada</option>
|
||||||
|
<option value="uk">United Kingdom</option>
|
||||||
|
<option value="au">Australia</option>
|
||||||
|
<option value="other">Other</option>
|
||||||
|
</select>
|
||||||
|
<div class="error-message" id="country-error">
|
||||||
|
Please select a country
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="register-btn">
|
||||||
|
Create Account
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Basic client-side validation
|
||||||
|
document
|
||||||
|
.getElementById("user-registration-form")
|
||||||
|
.addEventListener("submit", function (event) {
|
||||||
|
let isValid = true;
|
||||||
|
|
||||||
|
// First Name Validation
|
||||||
|
const firstName = document.getElementById("first-name");
|
||||||
|
const firstNameError =
|
||||||
|
document.getElementById("first-name-error");
|
||||||
|
if (firstName.value.trim().length < 2) {
|
||||||
|
firstNameError.style.display = "block";
|
||||||
|
isValid = false;
|
||||||
|
} else {
|
||||||
|
firstNameError.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last Name Validation
|
||||||
|
const lastName = document.getElementById("last-name");
|
||||||
|
const lastNameError =
|
||||||
|
document.getElementById("last-name-error");
|
||||||
|
if (lastName.value.trim().length < 2) {
|
||||||
|
lastNameError.style.display = "block";
|
||||||
|
isValid = false;
|
||||||
|
} else {
|
||||||
|
lastNameError.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Email Validation
|
||||||
|
const email = document.getElementById("email");
|
||||||
|
const emailError = document.getElementById("email-error");
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
if (!emailRegex.test(email.value)) {
|
||||||
|
emailError.style.display = "block";
|
||||||
|
isValid = false;
|
||||||
|
} else {
|
||||||
|
emailError.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Password Validation
|
||||||
|
const password = document.getElementById("password");
|
||||||
|
const passwordError =
|
||||||
|
document.getElementById("password-error");
|
||||||
|
if (password.value.length < 8) {
|
||||||
|
passwordError.style.display = "block";
|
||||||
|
isValid = false;
|
||||||
|
} else {
|
||||||
|
passwordError.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Date of Birth Validation
|
||||||
|
// const dob = document.getElementById("date-of-birth");
|
||||||
|
// const dobError = document.getElementById("dob-error");
|
||||||
|
// const today = new Date();
|
||||||
|
// const birthDate = new Date(dob.value);
|
||||||
|
// let age = today.getFullYear() - birthDate.getFullYear();
|
||||||
|
// const monthDiff = today.getMonth() - birthDate.getMonth();
|
||||||
|
// if (
|
||||||
|
// monthDiff < 0 ||
|
||||||
|
// (monthDiff === 0 &&
|
||||||
|
// today.getDate() < birthDate.getDate())
|
||||||
|
// ) {
|
||||||
|
// age--;
|
||||||
|
// }
|
||||||
|
// if (age < 18) {
|
||||||
|
// dobError.style.display = "block";
|
||||||
|
// isValid = false;
|
||||||
|
// } else {
|
||||||
|
// dobError.style.display = "none";
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Country Validation
|
||||||
|
// const country = document.getElementById("country");
|
||||||
|
// const countryError =
|
||||||
|
// document.getElementById("country-error");
|
||||||
|
// if (country.value === "") {
|
||||||
|
// countryError.style.display = "block";
|
||||||
|
// isValid = false;
|
||||||
|
// } else {
|
||||||
|
// countryError.style.display = "none";
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Prevent form submission if validation fails
|
||||||
|
if (!isValid) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
41
src/user_controller.v
Normal file
41
src/user_controller.v
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import veb
|
||||||
|
import encoding.base64
|
||||||
|
import json
|
||||||
|
|
||||||
|
@['/controller/user/create'; post]
|
||||||
|
pub fn (mut app App) controller_create_user(mut ctx Context) veb.Result {
|
||||||
|
first_name := ctx.form['first_name']
|
||||||
|
last_name := ctx.form['last_name']
|
||||||
|
email := ctx.form['email']
|
||||||
|
password := ctx.form['password']
|
||||||
|
gender := ctx.form['gender']
|
||||||
|
|
||||||
|
// Create a map of field names and their values
|
||||||
|
fields := {
|
||||||
|
'first_name': first_name
|
||||||
|
'last_name': last_name
|
||||||
|
'email': email
|
||||||
|
'password': password
|
||||||
|
// Gender can be optional, so not including it in validation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for empty fields
|
||||||
|
mut empty_fields := []string{}
|
||||||
|
for field_name, value in fields {
|
||||||
|
if value == '' {
|
||||||
|
empty_fields << field_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any fields are empty, return error message
|
||||||
|
if empty_fields.len > 0 {
|
||||||
|
return ctx.text('The following fields cannot be empty: ${empty_fields.join(", ")}')
|
||||||
|
}
|
||||||
|
|
||||||
|
app.service_add_user(first_name, last_name, email, password, gender) or {
|
||||||
|
return ctx.text('error: ${err}')
|
||||||
|
}
|
||||||
|
return ctx.text('User created successfully')
|
||||||
|
}
|
@@ -4,7 +4,10 @@ module main
|
|||||||
pub struct User {
|
pub struct User {
|
||||||
mut:
|
mut:
|
||||||
id int @[primary; sql: serial]
|
id int @[primary; sql: serial]
|
||||||
username string @[sql_type: 'TEXT'; unique]
|
first_name string @[sql_type: 'TEXT']
|
||||||
|
last_name string @[sql_type: 'TEXT']
|
||||||
|
email string @[sql_type: 'TEXT'; unique]
|
||||||
password string @[sql_type: 'TEXT']
|
password string @[sql_type: 'TEXT']
|
||||||
|
gender string @[sql_type: 'TEXT']
|
||||||
tickets []Ticket @[fkey: 'user_id']
|
tickets []Ticket @[fkey: 'user_id']
|
||||||
}
|
}
|
||||||
|
33
src/user_service.v
Normal file
33
src/user_service.v
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import crypto.bcrypt
|
||||||
|
import databases
|
||||||
|
|
||||||
|
fn (app &App) service_add_user(first_name string, last_name string, email string, password string, gender string) ! {
|
||||||
|
mut db := databases.create_db_connection()!
|
||||||
|
|
||||||
|
defer {
|
||||||
|
db.close() or { panic(err) }
|
||||||
|
}
|
||||||
|
|
||||||
|
hashed_password := bcrypt.generate_from_password(password.bytes(), bcrypt.min_cost) or {
|
||||||
|
eprintln(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
user_model := User{
|
||||||
|
first_name: first_name
|
||||||
|
last_name: last_name
|
||||||
|
email: email
|
||||||
|
password: hashed_password
|
||||||
|
gender: gender
|
||||||
|
}
|
||||||
|
|
||||||
|
mut insert_error := ''
|
||||||
|
sql db {
|
||||||
|
insert user_model into User
|
||||||
|
} or { insert_error = err.msg() }
|
||||||
|
if insert_error != '' {
|
||||||
|
return error(insert_error)
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user