use hbox instead of richtextlabel for nested text tags, complete invite creation
This commit is contained in:
@@ -47,7 +47,7 @@
|
||||
<input id="password" type="password" placeholder="Password" required="true" />
|
||||
<button type="submit" id="submit">Log In</button>
|
||||
</form>
|
||||
<p style="text-center mt-4 text-[#999999] text-base">Don't have an account? <a href="/signup.html">Register here</a></p>
|
||||
<p style="text-center mt-4 text-[#999999] text-sm">Don't have an account? <a href="/signup.html">Register here</a></p>
|
||||
|
||||
<p id="log-output" style="min-h-24"></p>
|
||||
</div>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
}
|
||||
|
||||
.form-input {
|
||||
w-full p-3 border border-gray-600 rounded-md bg-[#374151] text-white active:border-red-500
|
||||
w-64 p-3 border border-gray-600 rounded-md bg-[#374151] text-white active:border-red-500
|
||||
}
|
||||
|
||||
.card {
|
||||
|
||||
@@ -7,6 +7,7 @@ local tldSelector = gurt.select('#tld-selector')
|
||||
local loadingElement = gurt.select('#tld-loading')
|
||||
local displayElement = gurt.select('#invite-code-display')
|
||||
local remainingElement = gurt.select('#remaining')
|
||||
local redeemBtn = gurt.select('#redeem-invite-btn')
|
||||
|
||||
local options
|
||||
|
||||
@@ -169,6 +170,10 @@ local function createInvite()
|
||||
displayElement.text = 'Invite code: ' .. inviteCode .. ' (copied to clipboard)'
|
||||
displayElement:show()
|
||||
Clipboard.write(inviteCode)
|
||||
|
||||
user.registrations_remaining = user.registrations_remaining - 1
|
||||
updateUserInfo()
|
||||
|
||||
print('Invite code created and copied to clipboard: ' .. inviteCode)
|
||||
else
|
||||
print('Failed to create invite: ' .. response:text())
|
||||
@@ -197,7 +202,11 @@ local function redeemInvite(code)
|
||||
updateUserInfo()
|
||||
|
||||
-- Clear form
|
||||
gurt.select('#invite-code-input').text = ''
|
||||
gurt.select('#invite-code-input').value = ''
|
||||
redeemBtn.text = 'Success!'
|
||||
gurt.setTimeout(function()
|
||||
redeemBtn.text = 'Redeem'
|
||||
end, 1000)
|
||||
else
|
||||
local error = response:text()
|
||||
showError('redeem-error', 'Failed to redeem invite: ' .. error)
|
||||
@@ -236,8 +245,8 @@ end)
|
||||
|
||||
gurt.select('#create-invite-btn'):on('click', createInvite)
|
||||
|
||||
gurt.select('#redeem-invite-btn'):on('click', function()
|
||||
local code = gurt.select('#invite-code-input').text
|
||||
redeemBtn:on('click', function()
|
||||
local code = gurt.select('#invite-code-input').value
|
||||
if code and code ~= '' then
|
||||
redeemInvite(code)
|
||||
end
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<input id="confirm-password" type="password" placeholder="Confirm Password" required="true" />
|
||||
<button type="submit" id="submit">Create Account</button>
|
||||
</form>
|
||||
<p style="text-center mt-4 text-[#999999] text-base">Already have an account? <a href="index.html">Login here</a></p>
|
||||
<p style="text-center mt-4 text-[#999999] text-sm">Already have an account? <a href="index.html">Login here</a></p>
|
||||
|
||||
<p id="log-output" style="min-h-24"></p>
|
||||
</div>
|
||||
|
||||
@@ -197,17 +197,32 @@ pub(crate) async fn create_invite(_ctx: &ServerContext, app_state: AppState, cla
|
||||
.collect()
|
||||
};
|
||||
|
||||
// Insert invite code into database
|
||||
let insert_result = sqlx::query(
|
||||
"INSERT INTO invite_codes (code, created_by, created_at) VALUES ($1, $2, $3)"
|
||||
)
|
||||
.bind(&invite_code)
|
||||
.bind(claims.user_id)
|
||||
.bind(Utc::now())
|
||||
.execute(&app_state.db)
|
||||
.await;
|
||||
let mut tx = app_state.db.begin().await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
match insert_result {
|
||||
let affected_rows = sqlx::query("UPDATE users SET registrations_remaining = registrations_remaining - 1 WHERE id = $1 AND registrations_remaining > 0")
|
||||
.bind(claims.user_id)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?
|
||||
.rows_affected();
|
||||
|
||||
if affected_rows == 0 {
|
||||
return Ok(GurtResponse::bad_request().with_json_body(&Error {
|
||||
msg: "No registrations remaining to create invite",
|
||||
error: "INSUFFICIENT_REGISTRATIONS".into(),
|
||||
})?);
|
||||
}
|
||||
|
||||
sqlx::query("INSERT INTO invite_codes (code, created_by, created_at) VALUES ($1, $2, $3)")
|
||||
.bind(&invite_code)
|
||||
.bind(claims.user_id)
|
||||
.bind(Utc::now())
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
match tx.commit().await {
|
||||
Ok(_) => {
|
||||
let response = serde_json::json!({
|
||||
"invite_code": invite_code
|
||||
@@ -252,7 +267,7 @@ pub(crate) async fn redeem_invite(ctx: &ServerContext, app_state: AppState, clai
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
sqlx::query("UPDATE users SET registrations_remaining = registrations_remaining + 3 WHERE id = $1")
|
||||
sqlx::query("UPDATE users SET registrations_remaining = registrations_remaining + 1 WHERE id = $1")
|
||||
.bind(claims.user_id)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
@@ -262,7 +277,7 @@ pub(crate) async fn redeem_invite(ctx: &ServerContext, app_state: AppState, clai
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
let response = serde_json::json!({
|
||||
"registrations_added": 3
|
||||
"registrations_added": 1
|
||||
});
|
||||
Ok(GurtResponse::ok().with_json_body(&response)?)
|
||||
}
|
||||
@@ -282,20 +297,6 @@ pub(crate) async fn redeem_invite(ctx: &ServerContext, app_state: AppState, clai
|
||||
}
|
||||
|
||||
pub(crate) async fn create_domain_invite(_ctx: &ServerContext, app_state: AppState, claims: Claims) -> Result<GurtResponse> {
|
||||
// Check if user has domain invite codes remaining
|
||||
let user: (i32,) = sqlx::query_as("SELECT domain_invite_codes FROM users WHERE id = $1")
|
||||
.bind(claims.user_id)
|
||||
.fetch_one(&app_state.db)
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("User not found"))?;
|
||||
|
||||
if user.0 <= 0 {
|
||||
return Ok(GurtResponse::bad_request().with_json_body(&Error {
|
||||
msg: "No domain invite codes remaining",
|
||||
error: "NO_INVITES_REMAINING".into(),
|
||||
})?);
|
||||
}
|
||||
|
||||
// Generate random domain invite code
|
||||
let invite_code: String = {
|
||||
use rand::Rng;
|
||||
@@ -312,6 +313,20 @@ pub(crate) async fn create_domain_invite(_ctx: &ServerContext, app_state: AppSta
|
||||
let mut tx = app_state.db.begin().await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
let affected_rows = sqlx::query("UPDATE users SET domain_invite_codes = domain_invite_codes - 1 WHERE id = $1 AND domain_invite_codes > 0")
|
||||
.bind(claims.user_id)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?
|
||||
.rows_affected();
|
||||
|
||||
if affected_rows == 0 {
|
||||
return Ok(GurtResponse::bad_request().with_json_body(&Error {
|
||||
msg: "No domain invite codes remaining",
|
||||
error: "NO_INVITES_REMAINING".into(),
|
||||
})?);
|
||||
}
|
||||
|
||||
sqlx::query(
|
||||
"INSERT INTO domain_invite_codes (code, created_by, created_at) VALUES ($1, $2, $3)"
|
||||
)
|
||||
@@ -322,12 +337,6 @@ pub(crate) async fn create_domain_invite(_ctx: &ServerContext, app_state: AppSta
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
sqlx::query("UPDATE users SET domain_invite_codes = domain_invite_codes - 1 WHERE id = $1")
|
||||
.bind(claims.user_id)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
tx.commit().await
|
||||
.map_err(|_| GurtError::invalid_message("Database error"))?;
|
||||
|
||||
|
||||
@@ -85,14 +85,23 @@ pub(crate) async fn create_logic(domain: Domain, user_id: i32, app: &AppState) -
|
||||
|
||||
let domain_id = domain_row.0;
|
||||
|
||||
// Decrease user's registrations remaining
|
||||
sqlx::query(
|
||||
"UPDATE users SET registrations_remaining = registrations_remaining - 1 WHERE id = $1",
|
||||
let affected_rows = sqlx::query(
|
||||
"UPDATE users SET registrations_remaining = registrations_remaining - 1 WHERE id = $1 AND registrations_remaining > 0",
|
||||
)
|
||||
.bind(user_id)
|
||||
.execute(&app.db)
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("Failed to update user registrations"))?;
|
||||
.map_err(|_| GurtError::invalid_message("Failed to update user registrations"))?
|
||||
.rows_affected();
|
||||
|
||||
if affected_rows == 0 {
|
||||
sqlx::query("DELETE FROM domains WHERE id = $1")
|
||||
.bind(domain_id)
|
||||
.execute(&app.db)
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("Database cleanup error"))?;
|
||||
return Err(GurtError::invalid_message("No registrations remaining"));
|
||||
}
|
||||
|
||||
if !app.config.discord.bot_token.is_empty() && app.config.discord.channel_id != 0 {
|
||||
let domain_registration = DomainRegistration {
|
||||
@@ -123,20 +132,6 @@ pub(crate) async fn create_domain(
|
||||
app_state: AppState,
|
||||
claims: Claims,
|
||||
) -> Result<GurtResponse> {
|
||||
// Check if user has registrations remaining
|
||||
let user: (i32,) = sqlx::query_as("SELECT registrations_remaining FROM users WHERE id = $1")
|
||||
.bind(claims.user_id)
|
||||
.fetch_one(&app_state.db)
|
||||
.await
|
||||
.map_err(|_| GurtError::invalid_message("User not found"))?;
|
||||
|
||||
if user.0 <= 0 {
|
||||
return Ok(GurtResponse::bad_request().with_json_body(&Error {
|
||||
msg: "Failed to create domain",
|
||||
error: "No registrations remaining".into(),
|
||||
})?);
|
||||
}
|
||||
|
||||
let domain: Domain = serde_json::from_slice(ctx.body())
|
||||
.map_err(|_| GurtError::invalid_message("Invalid JSON"))?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user