forked from cereci5049/8
Merge pull request 'main' (#2) from cereci5049/8:main into main
Reviewed-on: #2
This commit is contained in:
commit
ee42d00896
22 changed files with 582 additions and 116 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -2,3 +2,5 @@
|
|||
.env
|
||||
hi.html
|
||||
hi.css
|
||||
hh1
|
||||
hh1.exe
|
14
Dockerfile
Normal file
14
Dockerfile
Normal file
|
@ -0,0 +1,14 @@
|
|||
FROM nimlang/nim:2.0.8-alpine
|
||||
|
||||
# RUN apk add sqlite-dev
|
||||
|
||||
ENV PORT 8080
|
||||
EXPOSE 8080
|
||||
|
||||
WORKDIR /a3
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN nimble install -y
|
||||
|
||||
ENTRYPOINT [ "nim", "c", "-d:ssl", "-r", "src/hh1.nim" ]
|
|
@ -12,6 +12,6 @@ bin = @["hh1"]
|
|||
# Dependencies
|
||||
|
||||
requires "nim >= 2.0.8"
|
||||
requires "https://github.com/ire4ever1190/mike"
|
||||
requires "https://github.com/ire4ever1190/mike >= 1.3.3"
|
||||
requires "nimja"
|
||||
requires "https://codeberg.org/13thab/turso-nim"
|
47
src/controller/login.nim
Normal file
47
src/controller/login.nim
Normal file
|
@ -0,0 +1,47 @@
|
|||
import
|
||||
mike,
|
||||
json,
|
||||
httpClient,
|
||||
../lib/[mics, htmx],
|
||||
../db/users,
|
||||
../model/rand
|
||||
|
||||
proc htmxLogin*(ctx: Context) =
|
||||
var
|
||||
form = ctx.urlForm
|
||||
|
||||
em =form["email"]
|
||||
ps=form["password"]
|
||||
|
||||
val: Validity
|
||||
validity = initTable[string, Validity]()
|
||||
|
||||
ctx &= initCookie("user2", "$(%* temp[1])")
|
||||
if em.len==0 or ps.len==0:
|
||||
for a, b in form:
|
||||
if form[a] == "":
|
||||
val.name = ""
|
||||
val.message = "Field is Required"
|
||||
val.mark = "is-invalid"
|
||||
validity[a] = val
|
||||
else:
|
||||
val.name = b
|
||||
val.message = ""
|
||||
val.mark = ""
|
||||
validity[a] = val
|
||||
ctx.send(htmxLogin(validity, ""))
|
||||
|
||||
let conn=newTurso()
|
||||
var temp=getUser(conn, em, ps)
|
||||
if temp[0] == true:
|
||||
ctx &= initCookie("user1", $(%* temp[1]))
|
||||
echo $(%* temp[1])
|
||||
echo ctx.cookies
|
||||
ctx.response.headers.add("HX-Redirect", "/")
|
||||
else:
|
||||
for a, b in form:
|
||||
val.name = b
|
||||
val.message = ""
|
||||
val.mark = ""
|
||||
validity[a] = val
|
||||
ctx.send(htmxLogin(validity, "Invalid Email or Password"))
|
|
@ -8,7 +8,10 @@ import
|
|||
|
||||
proc signup*(ctx: Context): string=
|
||||
if ctx.httpMethod == HttpGet:
|
||||
compileTemplateFile(getScriptDir() / "view" / "signup.nimja")
|
||||
var
|
||||
user1 = ctx.cookies.getOrDefault("user1", "")
|
||||
user = getUserFromCookie(user1)
|
||||
compileTemplateFile(".." / "view" / "signup.nimja", baseDir = getScriptDir())
|
||||
elif ctx.httpMethod == HttpPost:
|
||||
var
|
||||
firstName = ctx.urlForm["fn"]
|
||||
|
|
BIN
src/db/db_up
BIN
src/db/db_up
Binary file not shown.
BIN
src/db/db_up.exe
BIN
src/db/db_up.exe
Binary file not shown.
|
@ -1,7 +1,8 @@
|
|||
import
|
||||
./users,
|
||||
./[users, products],
|
||||
../lib/mics
|
||||
|
||||
var conn = newTurso()
|
||||
|
||||
setupUsers(conn)
|
||||
setupProducts(conn)
|
|
@ -0,0 +1,22 @@
|
|||
import
|
||||
turso,
|
||||
strformat,
|
||||
json,
|
||||
strutils,
|
||||
../model/model
|
||||
|
||||
proc setupProducts*(conn: Turso) =
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS Products (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
price REAL,
|
||||
quantity INTEGER,
|
||||
sellerId INTEGER,
|
||||
createdAt TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updatedAt TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
imageLink TEXT,
|
||||
FOREIGN KEY (sellerId) REFERENCES Users(idd)
|
||||
)
|
||||
""")
|
|
@ -7,25 +7,37 @@ import
|
|||
|
||||
proc setupUsers*(conn: Turso) =
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
CREATE TABLE IF NOT EXISTS Users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
first_name VARCHAR(255) NOT NULL,
|
||||
last_name VARCHAR(255) NOT NULL,
|
||||
firstName VARCHAR(255) NOT NULL,
|
||||
lastName VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) NOT NULL,
|
||||
phone VARCHAR(255) NOT NULL,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
created_at TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updated_at TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
access_level INTEGER NOT NULL
|
||||
createdAt TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updatedAt TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
accessLevel INTEGER NOT NULL
|
||||
)
|
||||
""")
|
||||
|
||||
proc createPost*(conn: Turso, user: User)=
|
||||
conn.execute(fmt"""INSERT INTO users (first_name, last_name, email, phone, password, access_level) VALUES ("{user.firstName}", "{user.lastName}", "{user.email}", "{user.phone}", "{user.password}", {user.accessLevel});""")
|
||||
conn.execute(fmt"""INSERT INTO users (firstName, lastName, email, phone, password, accessLevel) VALUES ("{user.firstName}", "{user.lastName}", "{user.email}", "{user.phone}", "{user.password}", {user.accessLevel});""")
|
||||
|
||||
proc getUser*(conn: Turso, email: string, password: string): (bool, User)=
|
||||
echo "h1"
|
||||
var
|
||||
data = conn.getData(fmt"""SELECT * FROM users WHERE email = "{email}" and password = "{password}";""")
|
||||
user = User(
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
password: "",
|
||||
accessLevel: 0
|
||||
)
|
||||
|
||||
if data["rows"].len > 0:
|
||||
echo "h2"
|
||||
user = User(
|
||||
firstName: data["rows"][0][1]["value"].getStr(),
|
||||
lastName: data["rows"][0][2]["value"].getStr(),
|
||||
|
@ -34,8 +46,7 @@ proc getUser*(conn: Turso, email: string, password: string): (bool, User)=
|
|||
password: data["rows"][0][5]["value"].getStr(),
|
||||
accessLevel: parseInt(data["rows"][0][8]["value"].getStr())
|
||||
)
|
||||
|
||||
if user.firstName.len == 0 or user.lastName.len == 0 or user.email.len == 0 or user.password.len == 0:
|
||||
result = (false, user)
|
||||
else:
|
||||
result = (true, user)
|
||||
else:
|
||||
echo "h3"
|
||||
result = (false, user)
|
BIN
src/hh1
BIN
src/hh1
Binary file not shown.
BIN
src/hh1.exe
BIN
src/hh1.exe
Binary file not shown.
120
src/hh1.nim
120
src/hh1.nim
|
@ -4,54 +4,128 @@ import
|
|||
strutils,
|
||||
json,
|
||||
strformat,
|
||||
./lib/mics,
|
||||
httpClient,
|
||||
dotenv,
|
||||
./lib/[mics, htmx],
|
||||
./db/users,
|
||||
./model/model,
|
||||
./controller/signup
|
||||
./model/[model, rand],
|
||||
./controller/[signup, login]
|
||||
|
||||
load()
|
||||
|
||||
"/^path" -> before[post, get]:
|
||||
var path2 = ctx.pathParams["path"]
|
||||
echo(fmt"[mike] before request: {ctx.httpMethod} {path2}")
|
||||
|
||||
"/" -> [get, post]:
|
||||
let user = ctx[User]
|
||||
compileTemplateFile(getScriptDir() / "view" / "index.nimja")
|
||||
var
|
||||
user1 = ctx.cookies.getOrDefault("user1", "")
|
||||
user = getUserFromCookie(user1)
|
||||
echo user.firstName
|
||||
compileTemplateFile("view" / "index.nimja", baseDir = getScriptDir())
|
||||
|
||||
"/shop" -> get:
|
||||
compileTemplateFile(getScriptDir() / "view" / "shop.nimja")
|
||||
var
|
||||
user1 = ctx.cookies.getOrDefault("user1", "")
|
||||
user = getUserFromCookie(user1)
|
||||
compileTemplateFile("view" / "shop.nimja", baseDir = getScriptDir())
|
||||
|
||||
"/contact" -> get:
|
||||
compileTemplateFile(getScriptDir() / "view" / "contact.nimja")
|
||||
var
|
||||
user1 = ctx.cookies.getOrDefault("user1", "")
|
||||
user = getUserFromCookie(user1)
|
||||
compileTemplateFile("view" / "contact.nimja", baseDir = getScriptDir())
|
||||
|
||||
"/cart" -> get:
|
||||
compileTemplateFile(getScriptDir() / "view" / "cart.nimja")
|
||||
var
|
||||
user1 = ctx.cookies.getOrDefault("user1", "")
|
||||
user = getUserFromCookie(user1)
|
||||
compileTemplateFile("view" / "cart.nimja", baseDir = getScriptDir())
|
||||
|
||||
"/checkout" -> get:
|
||||
compileTemplateFile(getScriptDir() / "view" / "checkout.nimja")
|
||||
var
|
||||
user1 = ctx.cookies.getOrDefault("user1", "")
|
||||
user = getUserFromCookie(user1)
|
||||
compileTemplateFile("view" / "checkout.nimja", baseDir = getScriptDir())
|
||||
|
||||
"/shop/:id" -> get:
|
||||
var prodId = capitalizeAscii(ctx.pathParams["id"])
|
||||
compileTemplateFile(getScriptDir() / "view" / "shop-detail.nimja")
|
||||
var
|
||||
prodId = capitalizeAscii(ctx.pathParams["id"])
|
||||
user1 = ctx.cookies.getOrDefault("user1", "")
|
||||
user = getUserFromCookie(user1)
|
||||
compileTemplateFile("view" / "shop-detail.nimja", baseDir = getScriptDir())
|
||||
|
||||
"/testimonial" -> get:
|
||||
compileTemplateFile(getScriptDir() / "view" / "testimonial.nimja")
|
||||
var
|
||||
user1 = ctx.cookies.getOrDefault("user1", "")
|
||||
user = getUserFromCookie(user1)
|
||||
compileTemplateFile("view" / "testimonial.nimja", baseDir = getScriptDir())
|
||||
|
||||
"/signup" -> [get, post]: ctx.signup()
|
||||
|
||||
"/login" -> get:
|
||||
compileTemplateFile(getScriptDir() / "view" / "login.nimja")
|
||||
var
|
||||
user1 = ctx.cookies.getOrDefault("user1", "")
|
||||
user = getUserFromCookie(user1)
|
||||
compileTemplateFile("view" / "login.nimja", baseDir = getScriptDir())
|
||||
|
||||
"/htmx/login" -> post: ctx.htmxLogin()
|
||||
|
||||
"/htmx/email" -> post:
|
||||
var
|
||||
em = ctx.urlForm["email"]
|
||||
val: Validity
|
||||
if em == "":
|
||||
val.message = "Last Name is Required"
|
||||
val.mark = "is-invalid"
|
||||
else:
|
||||
val.message = ""
|
||||
val.mark = ""
|
||||
ctx.send htmxEmail(em, val)
|
||||
|
||||
"/htmx/password" -> post:
|
||||
var
|
||||
pw = ctx.urlForm["password"]
|
||||
val: Validity
|
||||
if pw == "":
|
||||
val.message = "Last Name is Required"
|
||||
val.mark = "is-invalid"
|
||||
else:
|
||||
val.message = ""
|
||||
val.mark = ""
|
||||
ctx.send htmxPassword(pw, val)
|
||||
|
||||
"/:path" -> get:
|
||||
compileTemplateFile(getScriptDir() / "view" / "404.nimja")
|
||||
"/login"-> post:
|
||||
var em =ctx.urlForm["email"]
|
||||
var ps=ctx.urlForm["password"]
|
||||
let conn=newTurso()
|
||||
var temp=getUser(conn,em,ps)
|
||||
if temp[0]:
|
||||
ctx.redirect("/")
|
||||
else:
|
||||
echo "user not found"
|
||||
var
|
||||
user1 = ctx.cookies.getOrDefault("user1", "")
|
||||
user = getUserFromCookie(user1)
|
||||
compileTemplateFile("view" / "404.nimja", baseDir = getScriptDir())
|
||||
|
||||
"/hi" -> get:
|
||||
var
|
||||
user1 = ctx.cookies.getOrDefault("user1", "")
|
||||
user = getUserFromCookie(user1)
|
||||
uploadcare_pub_key = getEnv("UPLOAD_CARE_PUBLIC_KEY")
|
||||
compileTemplateFile("view" / "hi.nimja", baseDir = getScriptDir())
|
||||
|
||||
"/delete-hi" -> post:
|
||||
var
|
||||
client = newHttpClient()
|
||||
uploadcare_pub_key = getEnv("UPLOAD_CARE_PUBLIC_KEY")
|
||||
uploadcare_secret_key = getEnv("UPLOAD_CARE_SECRET_KEY")
|
||||
client.headers = newHttpHeaders({"Authorization": fmt"Uploadcare.Simple {uploadcare_pub_key}:{uploadcare_secret_key}"})
|
||||
var form = ctx.urlForm
|
||||
echo form
|
||||
var img_uuid = form["img1"]
|
||||
echo img_uuid
|
||||
echo fmt"https://api.uploadcare.com/files/{img_uuid}/storage/"
|
||||
try:
|
||||
let response = client.request(fmt"https://api.uploadcare.com/files/{img_uuid}/storage/", httpMethod = HttpDelete)
|
||||
echo response.status
|
||||
finally:
|
||||
client.close()
|
||||
var js = parseJson("""{"status": "success"}""")
|
||||
ctx.send(js)
|
||||
|
||||
servePublic("src/public", "/static")
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
import
|
||||
strformat,
|
||||
tables,
|
||||
../model/rand
|
||||
|
||||
proc htmxLogin*(val: Table[string, Validity], message: string): string =
|
||||
result = fmt"""
|
||||
<form id="input_form" class="" novalidate
|
||||
hx-trigger="submit"
|
||||
hx-post="/htmx/login"
|
||||
hx-target="#input_form"
|
||||
>
|
||||
|
||||
<label class="text-danger">{message}</label>
|
||||
<div class="form-group mt-5">
|
||||
<label for="email">Email:</label>
|
||||
<label class="text-danger">{val["email"].message}</label>
|
||||
<input type="email" name="email" id="email" class="form-control {val["email"].mark}" required autocomplete="off" value="{val["email"].name}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password">Password:</label>
|
||||
<label class="text-danger">{val["password"].message}</label>
|
||||
<input type="password" name="password" id="password" class="form-control {val["password"].mark}" required autocomplete="off" value="{val["password"].name}">
|
||||
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<button id="b4" type="submit" class="btn btn-primary">Submit</button>
|
||||
<a id="b4" href="/signup" class="btn btn-outline-primary">Sign Up</a>
|
||||
<hr>
|
||||
</form>
|
||||
"""
|
||||
|
||||
proc htmxEmail*(email: string, input: Validity): string =
|
||||
result = fmt"""
|
||||
<div class="form-group mt-5"
|
||||
hx-target="this"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
<label for="email">Email:</label>
|
||||
<label class="text-danger">{input.message}</label>
|
||||
<input type="email" name="email" id="email" class="form-control {input.mark}" required autocomplete="off"
|
||||
hx-post="/htmx/email"
|
||||
value="{email}"
|
||||
>
|
||||
</div>"""
|
||||
|
||||
proc htmxPassword*(password: string, input: Validity): string =
|
||||
result = fmt"""
|
||||
<div class="form-group"
|
||||
hx-target="this"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
<label for="password">Password:</label>
|
||||
<label class="text-danger">{input.message}</label>
|
||||
<input type="password" name="password" id="password" class="form-control {input.mark}" required autocomplete="off"
|
||||
hx-post="/htmx/password"
|
||||
value="{password}"
|
||||
>
|
||||
</div>"""
|
|
@ -2,6 +2,8 @@ import
|
|||
turso,
|
||||
dotenv,
|
||||
os,
|
||||
mike,
|
||||
json,
|
||||
../model/model
|
||||
|
||||
load()
|
||||
|
@ -9,3 +11,16 @@ load()
|
|||
proc newTurso*(): Turso =
|
||||
echo getEnv("DATABASE_URL")
|
||||
result = connect(getEnv("DATABASE_URL"), getEnv("AUTH_TOKEN"))
|
||||
|
||||
proc getUserFromCookie*(user: string): User =
|
||||
if user == "":
|
||||
return User(
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
password: "",
|
||||
accessLevel: 0
|
||||
)
|
||||
else:
|
||||
return to(parseJson(user), User)
|
5
src/model/rand.nim
Normal file
5
src/model/rand.nim
Normal file
|
@ -0,0 +1,5 @@
|
|||
type
|
||||
Validity* = object
|
||||
name*: string
|
||||
message*: string
|
||||
mark*: string
|
155
src/view/hi.nimja
Normal file
155
src/view/hi.nimja
Normal file
|
@ -0,0 +1,155 @@
|
|||
{% extends "view/partials/_master.nimja" %}
|
||||
|
||||
{% block css %}
|
||||
|
||||
<link rel="stylesheet" href="/static/css/hi.css">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@uploadcare/blocks@0.48.0/web/lr-file-uploader-regular.min.css"
|
||||
/>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>Upload Product Image</h1>
|
||||
<script type="module">
|
||||
import * as LR from "https://cdn.jsdelivr.net/npm/@uploadcare/blocks@0.48.0/web/lr-file-uploader-regular.min.js";
|
||||
|
||||
LR.registerBlocks(LR);
|
||||
</script>
|
||||
<lr-config
|
||||
ctx-name="my-uploader"
|
||||
pubkey="{{uploadcare_pub_key}}"
|
||||
max-local-file-size-bytes="10000000"
|
||||
multiple="false"
|
||||
img-only="true"
|
||||
source-list="local, camera, dropbox, gdrive, gphotos"
|
||||
></lr-config>
|
||||
<lr-file-uploader-regular
|
||||
ctx-name="my-uploader"
|
||||
class="my-config"
|
||||
>
|
||||
</lr-file-uploader-regular>
|
||||
|
||||
|
||||
<!-- The provider node is used to listen to the change event -->
|
||||
<lr-upload-ctx-provider
|
||||
ctx-name="my-uploader"
|
||||
id="my-uploader-provider"
|
||||
></lr-upload-ctx-provider>
|
||||
|
||||
<div id="previews"></div>
|
||||
<script>
|
||||
const providerNode = document.getElementById('my-uploader-provider');
|
||||
const previewsNode = document.getElementById('previews');
|
||||
|
||||
providerNode.addEventListener('change', event => {
|
||||
renderFiles(event.detail.allEntries.filter((file) => file.status === 'success'));
|
||||
});
|
||||
|
||||
let url = "";
|
||||
let uuid = "";
|
||||
|
||||
function renderFiles(files) {
|
||||
const renderedFiles = files.map(file => {
|
||||
const imgNode = document.createElement('img');
|
||||
console.log(file);
|
||||
imgNode.setAttribute('src', file.cdnUrl);
|
||||
imgNode.setAttribute('alt', file.fileInfo.originalFilename);
|
||||
imgNode.setAttribute('width', '100');
|
||||
imgNode.setAttribute('height', '100');
|
||||
|
||||
url = file.cdnUrl;
|
||||
uuid = file.uuid;
|
||||
|
||||
return imgNode;
|
||||
});
|
||||
console.log(...renderedFiles);
|
||||
|
||||
let formData = new FormData();
|
||||
formData.append('img', url);
|
||||
formData.append('img1', uuid);
|
||||
console.log(formData);
|
||||
let data = new URLSearchParams(formData);
|
||||
// data.append('img', url);
|
||||
// data.append('img1', uuid);
|
||||
console.log(data);
|
||||
let btnNode = document.createElement('button');
|
||||
btnNode.setAttribute('id', 'b4');
|
||||
btnNode.setAttribute('type', 'submit');
|
||||
btnNode.setAttribute('class', 'btn btn-primary');
|
||||
btnNode.addEventListener('click', function() {
|
||||
console.log('Delete');
|
||||
console.log(url);
|
||||
console.log(uuid);
|
||||
fetch('/delete-hi', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: data,
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
console.log('Success:', data);
|
||||
// remove the image and the buttons from the preview
|
||||
previewsNode.replaceChildren();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
});
|
||||
// btnNode.addEventListener('click', function() {
|
||||
// console.log('Delete');
|
||||
// console.log(url);
|
||||
// console.log(uuid);
|
||||
// });
|
||||
// btnNode.addEventListener('click', function() {
|
||||
// console.log('Submit');
|
||||
// console.log(url);
|
||||
// console.log(uuid);
|
||||
// });
|
||||
btnNode.innerHTML = 'Delete';
|
||||
|
||||
let btnNode1 = document.createElement('button');
|
||||
btnNode1.setAttribute('id', 'b4');
|
||||
btnNode1.setAttribute('type', 'submit');
|
||||
btnNode1.setAttribute('class', 'btn btn-primary');
|
||||
btnNode1.innerHTML = 'Submit';
|
||||
btnNode1.addEventListener('click', function() {
|
||||
console.log('Submit');
|
||||
console.log(url);
|
||||
console.log(uuid);
|
||||
fetch('/jj', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
img: url,
|
||||
}),
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
console.log('Success:', data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
});
|
||||
|
||||
previewsNode.replaceChildren(...renderedFiles, btnNode, btnNode1);
|
||||
}
|
||||
|
||||
// TODO: Add a button to delete the image from the server
|
||||
// TODO: Add a button to submit the image url to the server
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -20,11 +20,11 @@
|
|||
<div id="carouselId" class="carousel slide position-relative" data-bs-ride="carousel">
|
||||
<div class="carousel-inner" role="listbox">
|
||||
<div class="carousel-item active rounded">
|
||||
<img src="img/hero-img-1.png" class="img-fluid w-100 h-100 bg-secondary rounded" alt="First slide">
|
||||
<img src="/static/img/hero-img-1.png" class="img-fluid w-100 h-100 bg-secondary rounded" alt="First slide">
|
||||
<a href="#" class="btn px-4 py-2 text-white rounded">Fruites</a>
|
||||
</div>
|
||||
<div class="carousel-item rounded">
|
||||
<img src="img/hero-img-2.jpg" class="img-fluid w-100 h-100 rounded" alt="Second slide">
|
||||
<img src="/static/img/hero-img-2.jpg" class="img-fluid w-100 h-100 rounded" alt="Second slide">
|
||||
<a href="#" class="btn px-4 py-2 text-white rounded">Vesitables</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -144,7 +144,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -160,7 +160,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -176,7 +176,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-2.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-2.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -192,7 +192,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-4.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-4.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -208,7 +208,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-3.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-3.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -224,7 +224,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-1.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-1.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -240,7 +240,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-2.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-2.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -256,7 +256,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -280,7 +280,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -296,7 +296,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-2.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-2.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -320,7 +320,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-1.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-1.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -336,7 +336,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-6.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-6.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -360,7 +360,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -376,7 +376,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-4.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-4.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -400,7 +400,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-3.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-3.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -416,7 +416,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-2.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-2.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -432,7 +432,7 @@
|
|||
<div class="col-md-6 col-lg-4 col-xl-3">
|
||||
<div class="rounded position-relative fruite-item">
|
||||
<div class="fruite-img">
|
||||
<img src="img/fruite-item-1.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/fruite-item-1.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-secondary px-3 py-1 rounded position-absolute" style="top: 10px; left: 10px;">Fruits</div>
|
||||
<div class="p-4 border border-secondary border-top-0 rounded-bottom">
|
||||
|
@ -463,7 +463,7 @@
|
|||
<div class="col-md-6 col-lg-4">
|
||||
<a href="#">
|
||||
<div class="service-item bg-secondary rounded border border-secondary">
|
||||
<img src="img/featur-1.jpg" class="img-fluid rounded-top w-100" alt="">
|
||||
<img src="/static/img/featur-1.jpg" class="img-fluid rounded-top w-100" alt="">
|
||||
<div class="px-4 rounded-bottom">
|
||||
<div class="service-content bg-primary text-center p-4 rounded">
|
||||
<h5 class="text-white">Fresh Apples</h5>
|
||||
|
@ -476,7 +476,7 @@
|
|||
<div class="col-md-6 col-lg-4">
|
||||
<a href="#">
|
||||
<div class="service-item bg-dark rounded border border-dark">
|
||||
<img src="img/featur-2.jpg" class="img-fluid rounded-top w-100" alt="">
|
||||
<img src="/static/img/featur-2.jpg" class="img-fluid rounded-top w-100" alt="">
|
||||
<div class="px-4 rounded-bottom">
|
||||
<div class="service-content bg-light text-center p-4 rounded">
|
||||
<h5 class="text-primary">Tasty Fruits</h5>
|
||||
|
@ -489,7 +489,7 @@
|
|||
<div class="col-md-6 col-lg-4">
|
||||
<a href="#">
|
||||
<div class="service-item bg-primary rounded border border-primary">
|
||||
<img src="img/featur-3.jpg" class="img-fluid rounded-top w-100" alt="">
|
||||
<img src="/static/img/featur-3.jpg" class="img-fluid rounded-top w-100" alt="">
|
||||
<div class="px-4 rounded-bottom">
|
||||
<div class="service-content bg-secondary text-center p-4 rounded">
|
||||
<h5 class="text-white">Exotic Vegitable</h5>
|
||||
|
@ -512,7 +512,7 @@
|
|||
<div class="owl-carousel vegetable-carousel justify-content-center">
|
||||
<div class="border border-primary rounded position-relative vesitable-item">
|
||||
<div class="vesitable-img">
|
||||
<img src="img/vegetable-item-6.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/vegetable-item-6.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-primary px-3 py-1 rounded position-absolute" style="top: 10px; right: 10px;">Vegetable</div>
|
||||
<div class="p-4 rounded-bottom">
|
||||
|
@ -526,7 +526,7 @@
|
|||
</div>
|
||||
<div class="border border-primary rounded position-relative vesitable-item">
|
||||
<div class="vesitable-img">
|
||||
<img src="img/vegetable-item-1.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/vegetable-item-1.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-primary px-3 py-1 rounded position-absolute" style="top: 10px; right: 10px;">Vegetable</div>
|
||||
<div class="p-4 rounded-bottom">
|
||||
|
@ -540,7 +540,7 @@
|
|||
</div>
|
||||
<div class="border border-primary rounded position-relative vesitable-item">
|
||||
<div class="vesitable-img">
|
||||
<img src="img/vegetable-item-3.png" class="img-fluid w-100 rounded-top bg-light" alt="">
|
||||
<img src="/static/img/vegetable-item-3.png" class="img-fluid w-100 rounded-top bg-light" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-primary px-3 py-1 rounded position-absolute" style="top: 10px; right: 10px;">Vegetable</div>
|
||||
<div class="p-4 rounded-bottom">
|
||||
|
@ -554,7 +554,7 @@
|
|||
</div>
|
||||
<div class="border border-primary rounded position-relative vesitable-item">
|
||||
<div class="vesitable-img">
|
||||
<img src="img/vegetable-item-4.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/vegetable-item-4.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-primary px-3 py-1 rounded position-absolute" style="top: 10px; right: 10px;">Vegetable</div>
|
||||
<div class="p-4 rounded-bottom">
|
||||
|
@ -568,7 +568,7 @@
|
|||
</div>
|
||||
<div class="border border-primary rounded position-relative vesitable-item">
|
||||
<div class="vesitable-img">
|
||||
<img src="img/vegetable-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/vegetable-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-primary px-3 py-1 rounded position-absolute" style="top: 10px; right: 10px;">Vegetable</div>
|
||||
<div class="p-4 rounded-bottom">
|
||||
|
@ -582,7 +582,7 @@
|
|||
</div>
|
||||
<div class="border border-primary rounded position-relative vesitable-item">
|
||||
<div class="vesitable-img">
|
||||
<img src="img/vegetable-item-6.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/vegetable-item-6.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-primary px-3 py-1 rounded position-absolute" style="top: 10px; right: 10px;">Vegetable</div>
|
||||
<div class="p-4 rounded-bottom">
|
||||
|
@ -596,7 +596,7 @@
|
|||
</div>
|
||||
<div class="border border-primary rounded position-relative vesitable-item">
|
||||
<div class="vesitable-img">
|
||||
<img src="img/vegetable-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/vegetable-item-5.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-primary px-3 py-1 rounded position-absolute" style="top: 10px; right: 10px;">Vegetable</div>
|
||||
<div class="p-4 rounded-bottom">
|
||||
|
@ -610,7 +610,7 @@
|
|||
</div>
|
||||
<div class="border border-primary rounded position-relative vesitable-item">
|
||||
<div class="vesitable-img">
|
||||
<img src="img/vegetable-item-6.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
<img src="/static/img/vegetable-item-6.jpg" class="img-fluid w-100 rounded-top" alt="">
|
||||
</div>
|
||||
<div class="text-white bg-primary px-3 py-1 rounded position-absolute" style="top: 10px; right: 10px;">Vegetable</div>
|
||||
<div class="p-4 rounded-bottom">
|
||||
|
@ -642,7 +642,7 @@
|
|||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="position-relative">
|
||||
<img src="img/baner-1.png" class="img-fluid w-100 rounded" alt="">
|
||||
<img src="/static/img/baner-1.png" class="img-fluid w-100 rounded" alt="">
|
||||
<div class="d-flex align-items-center justify-content-center bg-white rounded-circle position-absolute" style="width: 140px; height: 140px; top: 0; left: 0;">
|
||||
<h1 style="font-size: 100px;">1</h1>
|
||||
<div class="d-flex flex-column">
|
||||
|
@ -670,7 +670,7 @@
|
|||
<div class="p-4 rounded bg-light">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-6">
|
||||
<img src="img/best-product-1.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
<img src="/static/img/best-product-1.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<a href="#" class="h5">Organic Tomato</a>
|
||||
|
@ -691,7 +691,7 @@
|
|||
<div class="p-4 rounded bg-light">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-6">
|
||||
<img src="img/best-product-2.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
<img src="/static/img/best-product-2.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<a href="#" class="h5">Organic Tomato</a>
|
||||
|
@ -712,7 +712,7 @@
|
|||
<div class="p-4 rounded bg-light">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-6">
|
||||
<img src="img/best-product-3.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
<img src="/static/img/best-product-3.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<a href="#" class="h5">Organic Tomato</a>
|
||||
|
@ -733,7 +733,7 @@
|
|||
<div class="p-4 rounded bg-light">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-6">
|
||||
<img src="img/best-product-4.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
<img src="/static/img/best-product-4.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<a href="#" class="h5">Organic Tomato</a>
|
||||
|
@ -754,7 +754,7 @@
|
|||
<div class="p-4 rounded bg-light">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-6">
|
||||
<img src="img/best-product-5.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
<img src="/static/img/best-product-5.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<a href="#" class="h5">Organic Tomato</a>
|
||||
|
@ -775,7 +775,7 @@
|
|||
<div class="p-4 rounded bg-light">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-6">
|
||||
<img src="img/best-product-6.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
<img src="/static/img/best-product-6.jpg" class="img-fluid rounded-circle w-100" alt="">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<a href="#" class="h5">Organic Tomato</a>
|
||||
|
@ -794,7 +794,7 @@
|
|||
</div>
|
||||
<div class="col-md-6 col-lg-6 col-xl-3">
|
||||
<div class="text-center">
|
||||
<img src="img/fruite-item-1.jpg" class="img-fluid rounded" alt="">
|
||||
<img src="/static/img/fruite-item-1.jpg" class="img-fluid rounded" alt="">
|
||||
<div class="py-4">
|
||||
<a href="#" class="h5">Organic Tomato</a>
|
||||
<div class="d-flex my-3 justify-content-center">
|
||||
|
@ -811,7 +811,7 @@
|
|||
</div>
|
||||
<div class="col-md-6 col-lg-6 col-xl-3">
|
||||
<div class="text-center">
|
||||
<img src="img/fruite-item-2.jpg" class="img-fluid rounded" alt="">
|
||||
<img src="/static/img/fruite-item-2.jpg" class="img-fluid rounded" alt="">
|
||||
<div class="py-4">
|
||||
<a href="#" class="h5">Organic Tomato</a>
|
||||
<div class="d-flex my-3 justify-content-center">
|
||||
|
@ -828,7 +828,7 @@
|
|||
</div>
|
||||
<div class="col-md-6 col-lg-6 col-xl-3">
|
||||
<div class="text-center">
|
||||
<img src="img/fruite-item-3.jpg" class="img-fluid rounded" alt="">
|
||||
<img src="/static/img/fruite-item-3.jpg" class="img-fluid rounded" alt="">
|
||||
<div class="py-4">
|
||||
<a href="#" class="h5">Organic Tomato</a>
|
||||
<div class="d-flex my-3 justify-content-center">
|
||||
|
@ -845,7 +845,7 @@
|
|||
</div>
|
||||
<div class="col-md-6 col-lg-6 col-xl-3">
|
||||
<div class="text-center">
|
||||
<img src="img/fruite-item-4.jpg" class="img-fluid rounded" alt="">
|
||||
<img src="/static/img/fruite-item-4.jpg" class="img-fluid rounded" alt="">
|
||||
<div class="py-2">
|
||||
<a href="#" class="h5">Organic Tomato</a>
|
||||
<div class="d-flex my-3 justify-content-center">
|
||||
|
@ -923,7 +923,7 @@
|
|||
</div>
|
||||
<div class="d-flex align-items-center flex-nowrap">
|
||||
<div class="bg-secondary rounded">
|
||||
<img src="img/testimonial-1.jpg" class="img-fluid rounded" style="width: 100px; height: 100px;" alt="">
|
||||
<img src="/static/img/testimonial-1.jpg" class="img-fluid rounded" style="width: 100px; height: 100px;" alt="">
|
||||
</div>
|
||||
<div class="ms-4 d-block">
|
||||
<h4 class="text-dark">Client Name</h4>
|
||||
|
@ -948,7 +948,7 @@
|
|||
</div>
|
||||
<div class="d-flex align-items-center flex-nowrap">
|
||||
<div class="bg-secondary rounded">
|
||||
<img src="img/testimonial-1.jpg" class="img-fluid rounded" style="width: 100px; height: 100px;" alt="">
|
||||
<img src="/static/img/testimonial-1.jpg" class="img-fluid rounded" style="width: 100px; height: 100px;" alt="">
|
||||
</div>
|
||||
<div class="ms-4 d-block">
|
||||
<h4 class="text-dark">Client Name</h4>
|
||||
|
@ -973,7 +973,7 @@
|
|||
</div>
|
||||
<div class="d-flex align-items-center flex-nowrap">
|
||||
<div class="bg-secondary rounded">
|
||||
<img src="img/testimonial-1.jpg" class="img-fluid rounded" style="width: 100px; height: 100px;" alt="">
|
||||
<img src="/static/img/testimonial-1.jpg" class="img-fluid rounded" style="width: 100px; height: 100px;" alt="">
|
||||
</div>
|
||||
<div class="ms-4 d-block">
|
||||
<h4 class="text-dark">Client Name</h4>
|
||||
|
|
40
src/view/jj.nimja
Normal file
40
src/view/jj.nimja
Normal file
|
@ -0,0 +1,40 @@
|
|||
{% extends "view/partials/_master.nimja" %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1 class="mt-5">Login</h1>
|
||||
|
||||
<form method="post" id="input_form" class="" novalidate>
|
||||
|
||||
<label class="text-danger"></label>
|
||||
<div class="form-group mt-5">
|
||||
<label for="email">Email:</label>
|
||||
<label class="text-danger"></label>
|
||||
<input type="email" name="email" id="email" class="form-control" required autocomplete="off" value="">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password">Password:</label>
|
||||
<label class="text-danger"></label>
|
||||
<input type="password" name="password" id="password" class="form-control" required autocomplete="off" value="">
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="file" id="img" name="img" accept="image/*">
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<button id="b4" type="submit" class="btn btn-primary">Submit</button>
|
||||
<a id="b4" href="/signup" class="btn btn-outline-primary">Sign Up</a>
|
||||
<hr>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -8,34 +8,35 @@
|
|||
<div class="col">
|
||||
<h1 class="mt-5">Login</h1>
|
||||
|
||||
<form id="input_form" method="post" class="" novalidate>
|
||||
<form id="input_form" class="" novalidate
|
||||
hx-trigger="submit"
|
||||
hx-post="/htmx/login"
|
||||
hx-target="#input_form"
|
||||
>
|
||||
|
||||
{# <!-- <label class="text-danger">{{loginError}}</label> --> #}
|
||||
<label class="text-danger"></label>
|
||||
<div class="form-group mt-5">
|
||||
<div class="form-group mt-5"
|
||||
hx-target="this"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
<label for="email">Email:</label>
|
||||
{# <!-- <label class="text-danger">{{emailError}}</label> --> #}
|
||||
<label class="text-danger"></label>
|
||||
|
||||
{# <!-- {% if emailError != "" %}
|
||||
<input type="email" name="email" id="email" class="form-control is-invalid" required autocomplete="off">
|
||||
{% else %} --> #}
|
||||
<input type="email" name="email" id="email" class="form-control" required autocomplete="off" value="">
|
||||
{# <!-- {% endif %} --> #}
|
||||
|
||||
<input type="email" name="email" id="email" class="form-control" required autocomplete="off"
|
||||
value=""
|
||||
hx-post="/htmx/email"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-group"
|
||||
hx-target="this"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
<label for="password">Password:</label>
|
||||
{# <!-- <label class="text-danger">{{passwordError}}</label> --> #}
|
||||
<label class="text-danger"></label>
|
||||
|
||||
{# <!-- {% if passwordError != "" %}
|
||||
<input type="password" name="password" id="password" class="form-control is-invalid" required autocomplete="off">
|
||||
{% else %} --> #}
|
||||
<input type="password" name="password" id="password" class="form-control" required autocomplete="off" value="">
|
||||
{# <!-- {% endif %} --> #}
|
||||
|
||||
<input type="password" name="password" id="password" class="form-control" required autocomplete="off"
|
||||
value=""
|
||||
hx-post="/htmx/password"
|
||||
>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -76,13 +76,27 @@
|
|||
</div>
|
||||
<div class="d-flex m-3 me-0">
|
||||
<button class="btn-search btn border border-secondary btn-md-square rounded-circle bg-white me-4" data-bs-toggle="modal" data-bs-target="#searchModal"><i class="fas fa-search text-primary"></i></button>
|
||||
<a href="/cart" class="position-relative me-4 my-auto">
|
||||
{% if user1 != "" %}
|
||||
<div class="me-4 my-auto nav-item dropdown">
|
||||
<a href="#" class="fas fa-user fa-2x" data-bs-toggle="dropdown"></a>
|
||||
<div class="dropdown-menu m-0 bg-secondary rounded-0">
|
||||
<a href="/cart" class="dropdown-item">Cart</a>
|
||||
<a href="/checkout" class="dropdown-item">Chackout</a>
|
||||
<a href="/testimonial" class="dropdown-item">Testimonial</a>
|
||||
<a href="404.html" class="dropdown-item">404 Page</a>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<a href="/login" class="me-4 my-auto">
|
||||
<i class="fas fa-user fa-2x"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<a href="/cart" class="position-relative my-auto">
|
||||
<i class="fa fa-shopping-bag fa-2x"></i>
|
||||
<span class="position-absolute bg-secondary rounded-circle d-flex align-items-center justify-content-center text-dark px-1" style="top: -5px; left: 15px; height: 20px; min-width: 20px;">3</span>
|
||||
</a>
|
||||
<a href="/login" class="my-auto">
|
||||
<i class="fas fa-user fa-2x"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
@ -187,7 +201,7 @@
|
|||
<p>Email: Example@gmail.com</p>
|
||||
<p>Phone: +0123 4567 8910</p>
|
||||
<p>Payment Accepted</p>
|
||||
<img src="img/payment.png" class="img-fluid" alt="">
|
||||
<img src="/static/img/payment.png" class="img-fluid" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "view/partials/_master.nimja" %}
|
||||
{% extends "../view/partials/_master.nimja" %}
|
||||
|
||||
{% block spheader1 %} Sign Up {% endblock %}
|
||||
{% block spheader2 %} Sign Up {% endblock %}
|
||||
|
|
Loading…
Reference in a new issue