Skip to content

Commit

Permalink
feat: Add qrcode functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
ikurotime committed Jan 7, 2024
1 parent d55610d commit b7a74df
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 27 deletions.
56 changes: 56 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ sqlx = { version = "0.6", features = ["postgres", "runtime-tokio-rustls"] }
dotenv = "0.15.0"
rand = "0.8.5"
bcrypt = "0.15.0"
qrcode = "0.13.0"
40 changes: 39 additions & 1 deletion assets/main.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
! tailwindcss v3.4.0 | MIT License | https://tailwindcss.com
! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com
*/

/*
Expand Down Expand Up @@ -686,6 +686,10 @@ video {
border-width: 1px;
}

.border-2 {
border-width: 2px;
}

.border-x {
border-left-width: 1px;
border-right-width: 1px;
Expand All @@ -704,6 +708,16 @@ video {
border-color: rgb(211 211 211 / var(--tw-border-opacity));
}

.border-green-600 {
--tw-border-opacity: 1;
border-color: rgb(22 163 74 / var(--tw-border-opacity));
}

.border-red-600 {
--tw-border-opacity: 1;
border-color: rgb(220 38 38 / var(--tw-border-opacity));
}

.bg-\[\#f5f6f7\] {
--tw-bg-opacity: 1;
background-color: rgb(245 246 247 / var(--tw-bg-opacity));
Expand All @@ -719,6 +733,16 @@ video {
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
}

.bg-green-300 {
--tw-bg-opacity: 1;
background-color: rgb(134 239 172 / var(--tw-bg-opacity));
}

.bg-red-300 {
--tw-bg-opacity: 1;
background-color: rgb(252 165 165 / var(--tw-bg-opacity));
}

.bg-slate-100 {
--tw-bg-opacity: 1;
background-color: rgb(241 245 249 / var(--tw-bg-opacity));
Expand All @@ -738,6 +762,10 @@ video {
fill: #000;
}

.p-2 {
padding: 0.5rem;
}

.p-3 {
padding: 0.75rem;
}
Expand Down Expand Up @@ -840,11 +868,21 @@ video {
color: rgb(0 0 0 / var(--tw-text-opacity));
}

.text-green-900 {
--tw-text-opacity: 1;
color: rgb(20 83 45 / var(--tw-text-opacity));
}

.text-indigo-500 {
--tw-text-opacity: 1;
color: rgb(99 102 241 / var(--tw-text-opacity));
}

.text-red-900 {
--tw-text-opacity: 1;
color: rgb(127 29 29 / var(--tw-text-opacity));
}

.text-white {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
Expand Down
1 change: 1 addition & 0 deletions src/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ fn router() -> Router {
.nest("/api", routes::user_routes::get_routes())
.nest("/api/link", routes::link_routes::get_routes())
.nest("/api/auth", routes::auth_routes::get_routes())
.nest("/api/qrcode", routes::qrcode_routes::get_routes())
}
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async fn main() -> anyhow::Result<()> {
let url = dotenv::var("DATABASE_URL").expect("DATABASE_URL is not set in .env file");

let sqlx_connection = PgPoolOptions::new()
.max_connections(250) // TODO: Set this to a reasonable value
.max_connections(95) // TODO: Set this to a reasonable value
.connect(&url)
.await
.unwrap();
Expand Down
5 changes: 3 additions & 2 deletions src/routes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod auth_routes;
pub mod link_routes;
pub mod qrcode_routes;
pub mod user_routes;
pub mod web_routes;
pub mod link_routes;
pub mod auth_routes;
23 changes: 8 additions & 15 deletions src/routes/link_routes.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,32 @@
use crate::http::ApiContext;
use axum::{http::StatusCode, routing::post, Extension, Form, Router};
use crate::{
http::ApiContext,
structs::{LinkRequest, LinkResponse},
};
use axum::{routing::post, Extension, Form, Router};
use rand;
use rand::Rng;
use serde::Deserialize;
use sqlx::{Error, PgPool, Row};

#[derive(sqlx::FromRow, Debug, Deserialize)] // Add this line
struct LinkRequest {
original_url: String,
path: String,
}
#[derive(sqlx::FromRow, Debug, Deserialize)] // Add this line
struct LinkResponse {
short_url: String,
}
pub fn get_routes() -> Router {
Router::new().route("/", post(add_link))
}

async fn add_link(
ctx: Extension<ApiContext>,
Form(payload): Form<LinkRequest>,
) -> Result<String, StatusCode> {
) -> Result<String, String> {
// Store the links in the database
let link = match insert_link(&payload, &ctx.db).await {
Ok(link) => link,
Err(err) => {
eprintln!("Error inserting link: {}", err);
return Err(StatusCode::INTERNAL_SERVER_ERROR);
return Err("<div class=\"p-2 animate-in text-red-900 bg-red-300 border-2 border-red-600\">Something went wrong</div>".to_string());
}
};
//return html

Ok(format!(
"<div>Your link: <a href=\"http://lurl.es/{}\" target=\"_blank\">https://lurl.es/{}</a></div>",
"<div class=\"p-2 text-green-900 animate-in bg-green-300 border-2 border-green-600\">Your link: <a href=\"http://lurl.es/{}\" target=\"_blank\">https://lurl.es/{}</a></div>",
link.short_url, link.short_url
))
}
Expand Down
37 changes: 37 additions & 0 deletions src/routes/qrcode_routes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use axum::{http::StatusCode, routing::post, Form, Router};
use qrcode::render::svg;
use qrcode::QrCode;
use serde::Deserialize;
#[derive(sqlx::FromRow, Debug, Deserialize)] // Add this line
struct QRCodeRequest {
original_url: String,
}
#[derive(sqlx::FromRow, Debug, Deserialize)] // Add this line
struct QRCodeResponse {
_short_url: String,
}
pub fn get_routes() -> Router {
Router::new().route("/", post(add_qrcode))
}

async fn add_qrcode(
// ctx: Extension<ApiContext>,
Form(payload): Form<QRCodeRequest>,
) -> Result<String, StatusCode> {
Ok(generate_qr_from_qrcode(&payload.original_url))
}
fn generate_qr_from_qrcode(url: &str) -> String {
if let Ok(qr) = QrCode::with_error_correction_level(&url, qrcode::EcLevel::L) {
let svg = qr
.render()
.min_dimensions(100, 100)
.dark_color(svg::Color("#000000"))
.light_color(svg::Color("#ffffff"))
.build();

svg
} else {
// should never (only on very huge codes) happen.
"".to_string()
}
}
24 changes: 17 additions & 7 deletions src/structs/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use serde::{Deserialize, Serialize};

#[derive(Debug, sqlx::FromRow)]
pub struct User {
pub(crate) id: i32,
pub(crate) name: Option<String>,
pub(crate) email: Option<String>,
pub(crate) password: Option<String>,
}
// #[derive(Debug, sqlx::FromRow)]
// pub struct User {
// pub(crate) id: i32,
// pub(crate) name: Option<String>,
// pub(crate) email: Option<String>,
// pub(crate) password: Option<String>,
// }

#[derive(sqlx::FromRow, Debug, Serialize)]
pub struct LoginResponse {
Expand All @@ -28,3 +28,13 @@ pub struct RegisterRequest {
pub(crate) password: String,
pub(crate) password_confirm: String,
}

#[derive(sqlx::FromRow, Debug, Deserialize)] // Add this line
pub struct LinkRequest {
pub(crate) original_url: String,
pub(crate) path: String,
}
#[derive(sqlx::FromRow, Debug, Deserialize)] // Add this line
pub struct LinkResponse {
pub(crate) short_url: String,
}
11 changes: 10 additions & 1 deletion templates/components/tabs.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
/>
</div>
<div id="response-div"></div>
<div class="hidden p-2 text-green-900 bg-green-300 border-2 border-green-600"></div>
<div class="hidden p-2 text-red-900 bg-red-300 border-2 border-red-600">Something went wrong</div>
<button class="w-full py-3 mt-4 font-bold text-white bg-black">
Shorten link
</button>
Expand All @@ -56,7 +58,13 @@
>
<p><strong>QR Code:</strong></p>

<form hx-post="/api/qr" id="url" class="flex flex-col gap-3 rounded-b">
<form
hx-post="/api/qrcode"
id="url"
hx-target="#response-div-qr"
hx-swap="innerHTML"
class="flex flex-col gap-3 rounded-b"
>
<label for="original_url"><strong>Original URL</strong></label>
<input
class="p-3 border rounded border-[#d3d3d3]"
Expand All @@ -67,6 +75,7 @@
<button class="w-full py-3 mt-4 font-bold text-white bg-black">
Generate QR Code
</button>
<div id="response-div-qr" class="flex items-center justify-center w-full"></div"
</form>
</div>
</div>

0 comments on commit b7a74df

Please sign in to comment.