feat: Add promo codes
All checks were successful
Build Docker / Build Image (push) Successful in 21s
All checks were successful
Build Docker / Build Image (push) Successful in 21s
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,3 +6,5 @@ __pycache__/
|
||||
used.json
|
||||
|
||||
payments.json
|
||||
|
||||
promo.json
|
||||
|
||||
22
account.py
Normal file
22
account.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import os
|
||||
import dotenv
|
||||
import random
|
||||
|
||||
dotenv.load_dotenv()
|
||||
|
||||
EMAIL = os.getenv('LOGIN_EMAIL')
|
||||
PASSWORD = os.getenv('LOGIN_PASSWORD')
|
||||
|
||||
tokens = []
|
||||
|
||||
def login(email, password):
|
||||
if email == EMAIL and password == PASSWORD:
|
||||
token = str(random.randint(100000, 999999))
|
||||
tokens.append(token)
|
||||
return token
|
||||
return False
|
||||
|
||||
def token(token):
|
||||
if token in tokens:
|
||||
return True
|
||||
return False
|
||||
74
payments.py
74
payments.py
@@ -29,6 +29,10 @@ else:
|
||||
with open(path+'used.json', 'w') as f:
|
||||
json.dump(used, f, indent=4)
|
||||
|
||||
if not os.path.exists(path+'promo.json'):
|
||||
with open(path+'promo.json', 'w') as f:
|
||||
json.dump([], f, indent=4)
|
||||
|
||||
HNSaddress = os.getenv('ADDRESS')
|
||||
|
||||
names = {
|
||||
@@ -37,7 +41,7 @@ names = {
|
||||
}
|
||||
|
||||
|
||||
def generate_payment(name,email,mobile,address,country,cart,hns):
|
||||
def generate_payment(name,email,mobile,address,country,cart,hns,promo=False):
|
||||
# Generate a payment object
|
||||
payment_id = generate_payment_id()
|
||||
if payment_id == "ERROR":
|
||||
@@ -50,6 +54,11 @@ def generate_payment(name,email,mobile,address,country,cart,hns):
|
||||
if item['name'] in names:
|
||||
item['name'] = names[item['name']]
|
||||
|
||||
if promo:
|
||||
promo = promo["id"]
|
||||
usePromo(promo)
|
||||
|
||||
|
||||
payment = {
|
||||
"name": name,
|
||||
"email": email,
|
||||
@@ -59,6 +68,7 @@ def generate_payment(name,email,mobile,address,country,cart,hns):
|
||||
"hns": hns,
|
||||
"ID": finalPrice,
|
||||
"cart": cart,
|
||||
"promo": promo,
|
||||
"status": "Pending"
|
||||
}
|
||||
finalPriceDolarydoo = float(finalPrice) * 1000000
|
||||
@@ -135,6 +145,68 @@ def generate_payment_id():
|
||||
if id > 99:
|
||||
return "ERROR"
|
||||
|
||||
|
||||
def getPromo(code):
|
||||
with open(path+'promo.json', 'r') as f:
|
||||
promos = json.load(f)
|
||||
for promo in promos:
|
||||
if promo['id'] == code:
|
||||
return promo
|
||||
return False
|
||||
|
||||
|
||||
def getPromos():
|
||||
with open(path+'promo.json', 'r') as f:
|
||||
promos = json.load(f)
|
||||
return promos
|
||||
|
||||
def addPromo(id, constant, percent, uses):
|
||||
with open(path+'promo.json', 'r') as f:
|
||||
promos = json.load(f)
|
||||
|
||||
for promo in promos:
|
||||
if promo['id'] == id:
|
||||
return False
|
||||
|
||||
|
||||
promos.append({
|
||||
"id": id,
|
||||
"constant": constant,
|
||||
"percent": percent,
|
||||
"uses": uses
|
||||
})
|
||||
with open(path+'promo.json', 'w') as f:
|
||||
json.dump(promos, f, indent=4)
|
||||
return True
|
||||
|
||||
def deletePromo(id):
|
||||
with open(path+'promo.json', 'r') as f:
|
||||
promos = json.load(f)
|
||||
for promo in promos:
|
||||
if promo['id'] == id:
|
||||
promos.remove(promo)
|
||||
with open(path+'promo.json', 'w') as f:
|
||||
json.dump(promos, f, indent=4)
|
||||
return True
|
||||
return False
|
||||
|
||||
def usePromo(id):
|
||||
with open(path+'promo.json', 'r') as f:
|
||||
promos = json.load(f)
|
||||
for promo in promos:
|
||||
if promo['id'] == id:
|
||||
if promo['uses'] == "1":
|
||||
promos.remove(promo)
|
||||
elif promo['uses'] == "-1":
|
||||
return True
|
||||
|
||||
uses = int(promo['uses'])
|
||||
uses -= 1
|
||||
promo['uses'] = str(uses)
|
||||
with open(path+'promo.json', 'w') as f:
|
||||
json.dump(promos, f, indent=4)
|
||||
return True
|
||||
|
||||
if __name__ == '__main__':
|
||||
for i in range(10):
|
||||
generate_payment('Test', 'test@email.com', '123 Test St', [
|
||||
|
||||
35
render.py
35
render.py
@@ -68,7 +68,7 @@ def cart_total(cert):
|
||||
price = prices[path]
|
||||
else:
|
||||
name = path
|
||||
image = "tech/image2.jpg"
|
||||
image = "pins/pack1.jpg"
|
||||
price = 45
|
||||
|
||||
hns = usdToHNS(price, True)
|
||||
@@ -122,7 +122,7 @@ def usdToHNS(usd, returnInt=False):
|
||||
return hns
|
||||
|
||||
|
||||
def total_usd(cert):
|
||||
def total_usd(cert,promo):
|
||||
total = 0
|
||||
for item in cert:
|
||||
path = item['name']
|
||||
@@ -130,18 +130,33 @@ def total_usd(cert):
|
||||
total += prices[path] * int(item['quantity'])
|
||||
else:
|
||||
total += 45 * int(item['quantity'])
|
||||
|
||||
if promo:
|
||||
if promo["constant"]:
|
||||
total -= int(promo["constant"])
|
||||
else:
|
||||
total = total - (total * int(promo["percent"]) / 100)
|
||||
|
||||
return total
|
||||
|
||||
def total_hns(cert, returnInt=False):
|
||||
total = 0
|
||||
for item in cert:
|
||||
path = item['name']
|
||||
if path in prices:
|
||||
total += usdToHNS(prices[path],True) * int(item['quantity'])
|
||||
else:
|
||||
total += usdToHNS(45,True) * int(item['quantity'])
|
||||
def total_hns(cert, promo, returnInt=False):
|
||||
total = total_usd(cert, promo)
|
||||
total = usdToHNS(total,True)
|
||||
|
||||
if returnInt:
|
||||
return int(total)
|
||||
total ="{:,}".format(total)
|
||||
return total
|
||||
|
||||
|
||||
def promoList(promo):
|
||||
html = '<ul class="list-group">'
|
||||
for item in promo:
|
||||
discount = 0
|
||||
if item['constant']:
|
||||
discount = "$"+item['constant']
|
||||
else:
|
||||
discount = item['percent'] + '%'
|
||||
html += f'<li class="list-group-item"><span>Code: {item["id"]} | {discount} off (Uses Left {item["uses"]})</span><a class="btn btn-primary align-right" role="button" href="/promo/delete/{item["id"]}">Delete</a></li>'
|
||||
html += '</ul>'
|
||||
return html
|
||||
127
server.py
127
server.py
@@ -7,6 +7,7 @@ import json
|
||||
import render
|
||||
import payments
|
||||
import threading
|
||||
import account
|
||||
|
||||
app = Flask(__name__)
|
||||
dotenv.load_dotenv()
|
||||
@@ -170,13 +171,41 @@ def cart():
|
||||
else:
|
||||
cart = '[]'
|
||||
|
||||
promo_message = ''
|
||||
if 'promo' in cookies:
|
||||
promo = cookies['promo']
|
||||
else:
|
||||
promo = ''
|
||||
|
||||
cart = json.loads(cart)
|
||||
cartHtml = render.cart(cart)
|
||||
|
||||
total_usd = render.total_usd(cart)
|
||||
total_hns = render.total_hns(cart)
|
||||
if promo != '':
|
||||
promo = payments.getPromo(promo)
|
||||
if not promo:
|
||||
promo_message = 'Invalid promo code'
|
||||
promo = ''
|
||||
else:
|
||||
promo_message = f'Promo code {promo["id"]} applied'
|
||||
|
||||
return render_template('cart.html', year=year, cart=cartHtml, total_usd=total_usd, total_hns=total_hns)
|
||||
total_usd = render.total_usd(cart,promo)
|
||||
total_hns = render.total_hns(cart,promo)
|
||||
promoCode = ''
|
||||
if promo:
|
||||
promoCode = promo["id"]
|
||||
else:
|
||||
total_usd = render.total_usd(cart, False)
|
||||
total_hns = render.total_hns(cart, False)
|
||||
promoCode = ''
|
||||
|
||||
return render_template('cart.html', year=year, cart=cartHtml, total_usd=total_usd, total_hns=total_hns,promo=promoCode, promo_message=promo_message)
|
||||
|
||||
@app.route('/cart/promo', methods=['POST'])
|
||||
def cart_promo():
|
||||
data = request.form
|
||||
response = make_response(redirect('/cart'))
|
||||
response.set_cookie('promo', data['promo'])
|
||||
return response
|
||||
|
||||
@app.route('/payment')
|
||||
def payment():
|
||||
@@ -194,8 +223,17 @@ def payment():
|
||||
cart = json.loads(cart)
|
||||
cartHtml = render.cart_total(cart)
|
||||
|
||||
total_usd = render.total_usd(cart)
|
||||
total_hns = render.total_hns(cart)
|
||||
if 'promo' in cookies:
|
||||
promo = cookies['promo']
|
||||
promo = payments.getPromo(promo)
|
||||
total_usd = render.total_usd(cart,promo)
|
||||
total_hns = render.total_hns(cart,promo)
|
||||
else:
|
||||
promo = ''
|
||||
total_usd = render.total_usd(cart, False)
|
||||
total_hns = render.total_hns(cart, False)
|
||||
|
||||
|
||||
|
||||
return render_template('payment.html', year=year, cart=cartHtml, total_usd=total_usd, total_hns=total_hns)
|
||||
|
||||
@@ -212,8 +250,16 @@ def payment_post():
|
||||
return redirect('/cart')
|
||||
|
||||
cart = json.loads(cart)
|
||||
total_usd = render.total_usd(cart)
|
||||
total_hns = render.total_hns(cart)
|
||||
if 'promo' in cookies:
|
||||
promo = cookies['promo']
|
||||
promo = payments.getPromo(promo)
|
||||
total_usd = render.total_usd(cart,promo)
|
||||
total_hns = render.total_hns(cart,promo)
|
||||
else:
|
||||
promo = False
|
||||
total_usd = render.total_usd(cart, False)
|
||||
total_hns = render.total_hns(cart, False)
|
||||
|
||||
|
||||
data = request.form
|
||||
if 'email' in data:
|
||||
@@ -242,15 +288,13 @@ def payment_post():
|
||||
|
||||
cartHtml = render.cart_total(cart)
|
||||
|
||||
|
||||
if email == '' or address == '' or name == '' or country == '' or mobile == '':
|
||||
return render_template('payment.html', error='Please fill all fields',
|
||||
email=email, address=address, name=name, mobile=mobile, country=country,
|
||||
cart=cartHtml, total_usd=total_usd, total_hns=total_hns)
|
||||
|
||||
|
||||
# All good, check out
|
||||
payment = payments.generate_payment(name, email, mobile,address,country, cart, render.total_hns(cart, True))
|
||||
payment = payments.generate_payment(name, email, mobile,address,country, cart, render.total_hns(cart, promo,True), promo)
|
||||
|
||||
if payment == False:
|
||||
return render_template('payment.html', error='There was an error processing your payment', email=email, address=address, name=name,
|
||||
@@ -265,9 +309,67 @@ def payment_post():
|
||||
|
||||
responce = make_response(render_template('payment_info.html',cart=cartHtml, total_hns=finalPrice,address=HNSaddress, year=datetime.datetime.now().year, qr=qr))
|
||||
responce.set_cookie('cart', '[]')
|
||||
|
||||
return responce
|
||||
|
||||
|
||||
# Promo routes
|
||||
@app.route('/promo')
|
||||
def promo():
|
||||
year = datetime.datetime.now().year
|
||||
# Check user is logged in
|
||||
token = request.cookies.get('token')
|
||||
if not token:
|
||||
return redirect('/login')
|
||||
|
||||
if not account.token(token):
|
||||
return redirect('/login')
|
||||
|
||||
promos = payments.getPromos()
|
||||
promos = render.promoList(promos)
|
||||
|
||||
return render_template('promo.html', year=year, promos=promos)
|
||||
|
||||
@app.route('/promo', methods=['POST'])
|
||||
def promo_post():
|
||||
data = request.form
|
||||
token = request.cookies.get('token')
|
||||
if not token:
|
||||
return redirect('/login')
|
||||
|
||||
if not account.token(token):
|
||||
return redirect('/login')
|
||||
|
||||
id = data['code']
|
||||
constant = data['constant']
|
||||
percent = data['percent']
|
||||
uses = data['uses']
|
||||
payments.addPromo(id, constant, percent, uses)
|
||||
|
||||
return redirect('/promo')
|
||||
|
||||
@app.route('/promo/delete/<path:path>')
|
||||
def promo_delete(path):
|
||||
token = request.cookies.get('token')
|
||||
if not token:
|
||||
return redirect('/login')
|
||||
|
||||
if not account.token(token):
|
||||
return redirect('/login')
|
||||
|
||||
payments.deletePromo(path)
|
||||
return redirect('/promo')
|
||||
|
||||
@app.route('/login', methods=['POST'])
|
||||
def login():
|
||||
data = request.form
|
||||
token = account.login(data['email'], data['password'])
|
||||
if token:
|
||||
response = make_response(redirect('/promo'))
|
||||
response.set_cookie('token', token)
|
||||
return response
|
||||
return redirect('/login')
|
||||
|
||||
|
||||
# Main routes
|
||||
@app.route('/')
|
||||
def index():
|
||||
@@ -305,7 +407,4 @@ def check_payments():
|
||||
payments.check_payments()
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Set timer for payments
|
||||
|
||||
repeat_check_payments()
|
||||
app.run(debug=True, port=5000, host='0.0.0.0')
|
||||
10
templates/assets/css/vanilla-zoom.min.css
vendored
10
templates/assets/css/vanilla-zoom.min.css
vendored
@@ -39,3 +39,13 @@
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
position: absolute;
|
||||
right: 1px;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: medium !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
<div class="col-md-12 col-lg-4">
|
||||
<div class="bg-body-tertiary summary">
|
||||
<h3>Summary</h3>
|
||||
<form style="margin-bottom: 25px;" method="post" action="/cart/promo"><label class="form-label" for="promo">Promo Code</label><input class="form-control" type="text" placeholder="Promo Code" name="promo" value="{{promo}}"><span>{{promo_message}}</span></form>
|
||||
<h4 class="border-primary-subtle" style="border-color: var(--bs-primary-border-subtle);"><span class="text">Total USD</span><span class="price">US${{total_usd}}</span></h4>
|
||||
<h4><span class="text">Total</span><span class="price">{{total_hns}} HNS</span></h4><a class="btn btn-primary btn-lg d-block w-100" role="button" href="/payment">Checkout</a>
|
||||
</div>
|
||||
|
||||
109
templates/login.html
Normal file
109
templates/login.html
Normal file
@@ -0,0 +1,109 @@
|
||||
<!DOCTYPE html>
|
||||
<html data-bs-theme="dark" lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||
<title>Login - HNSAU</title>
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<link rel="canonical" href="https://hns.au/login">
|
||||
<meta property="og:url" content="https://hns.au/login">
|
||||
<meta name="twitter:image" content="https://hns.au/assets/img/HNSAUbanner.png">
|
||||
<meta name="twitter:description" content="The home of Australians using the decentralized web, built on Handshake.">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta property="og:description" content="The home of Australians using the decentralized web, built on Handshake.">
|
||||
<meta name="description" content="Handshake Australia">
|
||||
<meta property="og:title" content="HNS AU">
|
||||
<meta property="og:type" content="website">
|
||||
<meta name="twitter:title" content="HNS AU">
|
||||
<meta property="og:image" content="https://hns.au/assets/img/HNSAUbanner.png">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png" media="(prefers-color-scheme: dark)">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png" media="(prefers-color-scheme: dark)">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png">
|
||||
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
|
||||
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat:400,400i,700,700i,600,600i&display=swap">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/baguettebox.js/1.10.0/baguetteBox.min.css">
|
||||
<link rel="stylesheet" href="/assets/css/vanilla-zoom.min.css">
|
||||
<!-- Matomo -->
|
||||
<script>
|
||||
var _paq = window._paq = window._paq || [];
|
||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
(function() {
|
||||
var u="https://analytics.woodburn.au/";
|
||||
_paq.push(['setTrackerUrl', u+'matomo.php']);
|
||||
_paq.push(['setSiteId', '8']);
|
||||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
|
||||
})();
|
||||
</script>
|
||||
<!-- End Matomo Code -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg fixed-top bg-dark clean-navbar navbar-light" data-bs-theme="dark">
|
||||
<div class="container-fluid"><a class="navbar-brand logo" href="/" style="width: 50%;"><img src="/assets/img/favicon.png" style="height: 50px;margin-right: 10px;">HNSAU</a><button data-bs-toggle="collapse" class="navbar-toggler" data-bs-target="#navcol-1"><span class="visually-hidden">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
||||
<div class="collapse navbar-collapse" id="navcol-1">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/blog">Blog</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/links">Links</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/about">About Us</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="https://domains.hns.au">Domains</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/pins">Pins</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/contact">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="page login-page">
|
||||
<section class="clean-block clean-form dark">
|
||||
<div class="container">
|
||||
<div class="block-heading">
|
||||
<h2 class="text-info">Log In</h2>
|
||||
</div>
|
||||
<form method="post">
|
||||
<div class="mb-3"><label class="form-label" for="email">Email</label><input class="form-control item" type="email" id="email" data-bs-theme="light" name="email"></div>
|
||||
<div class="mb-3"><label class="form-label" for="password">Password</label><input class="form-control" type="password" id="password" data-bs-theme="light" name="password"></div><button class="btn btn-primary" type="submit">Log In</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer class="page-footer dark">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<h5>Get started</h5>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/links">Links</a></li>
|
||||
<li><a href="/domains" target="_blank">Domains</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<h5>Contact</h5>
|
||||
<ul>
|
||||
<li><a href="https://discord.gg/WJ6vpjuQv5" target="_blank">Discord</a></li>
|
||||
<li><a href="/email" target="_blank">Email</a></li>
|
||||
<li><a href="/about">About Us</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-copyright">
|
||||
<p>© {{year}} Handshake AU</p>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/baguettebox.js/1.10.0/baguetteBox.min.js"></script>
|
||||
<script src="/assets/js/vanilla-zoom.js"></script>
|
||||
<script src="/assets/js/theme.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
114
templates/promo.html
Normal file
114
templates/promo.html
Normal file
@@ -0,0 +1,114 @@
|
||||
<!DOCTYPE html>
|
||||
<html data-bs-theme="dark" lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||
<title>Login - HNSAU</title>
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<link rel="canonical" href="https://hns.au/promo">
|
||||
<meta property="og:url" content="https://hns.au/promo">
|
||||
<meta name="twitter:image" content="https://hns.au/assets/img/HNSAUbanner.png">
|
||||
<meta name="twitter:description" content="The home of Australians using the decentralized web, built on Handshake.">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta property="og:description" content="The home of Australians using the decentralized web, built on Handshake.">
|
||||
<meta name="description" content="Handshake Australia">
|
||||
<meta property="og:title" content="HNS AU">
|
||||
<meta property="og:type" content="website">
|
||||
<meta name="twitter:title" content="HNS AU">
|
||||
<meta property="og:image" content="https://hns.au/assets/img/HNSAUbanner.png">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png" media="(prefers-color-scheme: dark)">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png" media="(prefers-color-scheme: dark)">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png">
|
||||
<link rel="icon" type="image/png" sizes="600x627" href="/assets/img/favicon.png">
|
||||
<link rel="stylesheet" href="/assets/bootstrap/css/bootstrap.min.css">
|
||||
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat:400,400i,700,700i,600,600i&display=swap">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/baguettebox.js/1.10.0/baguetteBox.min.css">
|
||||
<link rel="stylesheet" href="/assets/css/vanilla-zoom.min.css">
|
||||
<!-- Matomo -->
|
||||
<script>
|
||||
var _paq = window._paq = window._paq || [];
|
||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
(function() {
|
||||
var u="https://analytics.woodburn.au/";
|
||||
_paq.push(['setTrackerUrl', u+'matomo.php']);
|
||||
_paq.push(['setSiteId', '8']);
|
||||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
|
||||
})();
|
||||
</script>
|
||||
<!-- End Matomo Code -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg fixed-top bg-dark clean-navbar navbar-light" data-bs-theme="dark">
|
||||
<div class="container-fluid"><a class="navbar-brand logo" href="/" style="width: 50%;"><img src="/assets/img/favicon.png" style="height: 50px;margin-right: 10px;">HNSAU</a><button data-bs-toggle="collapse" class="navbar-toggler" data-bs-target="#navcol-1"><span class="visually-hidden">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
|
||||
<div class="collapse navbar-collapse" id="navcol-1">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/blog">Blog</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/links">Links</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/about">About Us</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="https://domains.hns.au">Domains</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/pins">Pins</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/contact">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="page login-page">
|
||||
<section class="clean-block clean-form dark">
|
||||
<div class="container">
|
||||
<div class="block-heading">
|
||||
<h2 class="text-info">Create Promo Code</h2>
|
||||
</div>
|
||||
<form method="post">
|
||||
<div style="margin-bottom: 16px;"><label class="form-label" for="code">Code</label><input class="form-control" type="text" data-bs-theme="light" name="code" placeholder="Promo Code"></div>
|
||||
<div style="margin-bottom: 16px;"><label class="form-label" for="constant">US$ Off</label><input class="form-control" type="text" data-bs-theme="light" name="constant" placeholder="10"></div>
|
||||
<div style="margin-bottom: 16px;"><label class="form-label" for="percent">% Off</label><input class="form-control" type="text" data-bs-theme="light" name="percent" placeholder="25"></div>
|
||||
<div style="margin-bottom: 16px;"><label class="form-label" for="uses">Uses</label><input class="form-control" type="text" data-bs-theme="light" name="uses" placeholder="1"><span>Enter -1 for unlimited uses</span></div><button class="btn btn-primary" type="submit">Create</button>
|
||||
</form>
|
||||
</div>
|
||||
<div style="margin: auto;margin-top: 25px;max-width: 700px;">
|
||||
<h3 class="text-center">Existing Promo Codes</h3>{{promos | safe}}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer class="page-footer dark">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<h5>Get started</h5>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/links">Links</a></li>
|
||||
<li><a href="/domains" target="_blank">Domains</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<h5>Contact</h5>
|
||||
<ul>
|
||||
<li><a href="https://discord.gg/WJ6vpjuQv5" target="_blank">Discord</a></li>
|
||||
<li><a href="/email" target="_blank">Email</a></li>
|
||||
<li><a href="/about">About Us</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-copyright">
|
||||
<p>© {{year}} Handshake AU</p>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="/assets/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/baguettebox.js/1.10.0/baguetteBox.min.js"></script>
|
||||
<script src="/assets/js/vanilla-zoom.js"></script>
|
||||
<script src="/assets/js/theme.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -39,6 +39,9 @@
|
||||
<url>
|
||||
<loc>https://hns.au/links</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://hns.au/login</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://hns.au/payment</loc>
|
||||
</url>
|
||||
@@ -48,6 +51,9 @@
|
||||
<url>
|
||||
<loc>https://hns.au/pins</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://hns.au/promo</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://hns.au/uv</loc>
|
||||
</url>
|
||||
|
||||
Reference in New Issue
Block a user