This commit is contained in:
2025-03-06 01:53:40 +05:30
parent fd90a6d2a5
commit ca4dda7dcd
8 changed files with 171 additions and 30 deletions

View File

@@ -1,14 +1,19 @@
module main module main
import veb import veb
import databases import db.sqlite
import veb.auth
pub struct Context {
veb.Context
}
pub struct App { pub struct App {
veb.StaticHandler veb.StaticHandler
pub mut:
db sqlite.DB
auth auth.Auth[sqlite.DB]
}
pub struct Context {
veb.Context
user User
} }
pub fn (app &App) index(mut ctx Context) veb.Result { pub fn (app &App) index(mut ctx Context) veb.Result {
@@ -16,16 +21,17 @@ pub fn (app &App) index(mut ctx Context) veb.Result {
} }
fn main() { fn main() {
mut db := databases.create_db_connection() or { panic(err) } mut app := &App{
db: sqlite.connect('app.db')!
}
sql db { sql app.db {
create table User create table User
create table Plane create table Plane
create table Ticket create table Ticket
} or { panic('error on create table: ${err}') } } or { panic('error on create table: ${err}') }
db.close() or { panic(err) } app.auth = auth.new(app.db)
mut app := &App{}
app.handle_static('static', false)! app.handle_static('static', false)!

BIN
src/src

Binary file not shown.

View File

@@ -133,6 +133,7 @@
display: none; display: none;
} }
</style> </style>
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
</head> </head>
<body> <body>
<div class="container"> <div class="container">
@@ -142,7 +143,12 @@
</header> </header>
<section class="registration-form"> <section class="registration-form">
<form id="user-registration-form"> <form
id="user-registration-form"
hx-trigger="submit"
hx-post="/controller/user/create"
hx-target="#user-registration-form"
>
<div class="form-row"> <div class="form-row">
<div class="form-group"> <div class="form-group">
<label for="first-name">First Name</label> <label for="first-name">First Name</label>

View File

@@ -0,0 +1,132 @@
<form
id="user-registration-form"
hx-trigger="submit"
hx-post="/controller/user/create"
hx-target="#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>

View File

@@ -1,8 +1,6 @@
module main module main
import veb import veb
import encoding.base64
import json
@['/controller/user/create'; post] @['/controller/user/create'; post]
pub fn (mut app App) controller_create_user(mut ctx Context) veb.Result { pub fn (mut app App) controller_create_user(mut ctx Context) veb.Result {
@@ -15,9 +13,9 @@ pub fn (mut app App) controller_create_user(mut ctx Context) veb.Result {
// Create a map of field names and their values // Create a map of field names and their values
fields := { fields := {
'first_name': first_name 'first_name': first_name
'last_name': last_name 'last_name': last_name
'email': email 'email': email
'password': password 'password': password
// Gender can be optional, so not including it in validation // Gender can be optional, so not including it in validation
} }
@@ -31,7 +29,7 @@ pub fn (mut app App) controller_create_user(mut ctx Context) veb.Result {
// If any fields are empty, return error message // If any fields are empty, return error message
if empty_fields.len > 0 { if empty_fields.len > 0 {
return ctx.text('The following fields cannot be empty: ${empty_fields.join(", ")}') return ctx.text('The following fields cannot be empty: ${empty_fields.join(', ')}')
} }
app.service_add_user(first_name, last_name, email, password, gender) or { app.service_add_user(first_name, last_name, email, password, gender) or {

View File

@@ -10,4 +10,5 @@ mut:
password string @[sql_type: 'TEXT'] password string @[sql_type: 'TEXT']
gender string @[sql_type: 'TEXT'] gender string @[sql_type: 'TEXT']
tickets []Ticket @[fkey: 'user_id'] tickets []Ticket @[fkey: 'user_id']
salt string
} }

View File

@@ -1,30 +1,21 @@
module main module main
import crypto.bcrypt import veb.auth
import databases
fn (app &App) service_add_user(first_name string, last_name string, email string, password string, gender string) ! { fn (app &App) service_add_user(first_name string, last_name string, email string, password string, gender string) ! {
mut db := databases.create_db_connection()! salt := auth.generate_salt()
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{ user_model := User{
first_name: first_name first_name: first_name
last_name: last_name last_name: last_name
email: email email: email
password: hashed_password password: auth.hash_password_with_salt(password, salt)
gender: gender gender: gender
salt: salt
} }
mut insert_error := '' mut insert_error := ''
sql db { sql app.db {
insert user_model into User insert user_model into User
} or { insert_error = err.msg() } } or { insert_error = err.msg() }
if insert_error != '' { if insert_error != '' {

7
src/user_view.v Normal file
View File

@@ -0,0 +1,7 @@
module main
import veb
pub fn (app &App) signup(mut ctx Context) veb.Result {
return $veb.html()
}