mirror of
https://github.com/ae-utbm/sith.git
synced 2025-07-09 19:40:19 +00:00
@ -505,6 +505,8 @@ Welcome to the wiki page!
|
||||
refound.save()
|
||||
|
||||
# Counters
|
||||
subscribers = Group.objects.get(name="Subscribers")
|
||||
old_subscribers = Group.objects.get(name="Old subscribers")
|
||||
Customer(user=skia, account_id="6568j", amount=0).save()
|
||||
Customer(user=r, account_id="4000k", amount=0).save()
|
||||
p = ProductType(name="Bières bouteilles")
|
||||
@ -525,6 +527,9 @@ Welcome to the wiki page!
|
||||
club=main_club,
|
||||
)
|
||||
cotis.save()
|
||||
cotis.buying_groups.add(subscribers)
|
||||
cotis.buying_groups.add(old_subscribers)
|
||||
cotis.save()
|
||||
cotis2 = Product(
|
||||
name="Cotis 2 semestres",
|
||||
code="2SCOTIZ",
|
||||
@ -535,6 +540,9 @@ Welcome to the wiki page!
|
||||
club=main_club,
|
||||
)
|
||||
cotis2.save()
|
||||
cotis2.buying_groups.add(subscribers)
|
||||
cotis2.buying_groups.add(old_subscribers)
|
||||
cotis2.save()
|
||||
refill = Product(
|
||||
name="Rechargement 15 €",
|
||||
code="15REFILL",
|
||||
@ -545,6 +553,8 @@ Welcome to the wiki page!
|
||||
club=main_club,
|
||||
)
|
||||
refill.save()
|
||||
refill.buying_groups.add(subscribers)
|
||||
refill.save()
|
||||
barb = Product(
|
||||
name="Barbar",
|
||||
code="BARB",
|
||||
@ -553,8 +563,11 @@ Welcome to the wiki page!
|
||||
selling_price="1.7",
|
||||
special_selling_price="1.6",
|
||||
club=main_club,
|
||||
limit_age=18,
|
||||
)
|
||||
barb.save()
|
||||
barb.buying_groups.add(subscribers)
|
||||
barb.save()
|
||||
cble = Product(
|
||||
name="Chimay Bleue",
|
||||
code="CBLE",
|
||||
@ -563,8 +576,11 @@ Welcome to the wiki page!
|
||||
selling_price="1.7",
|
||||
special_selling_price="1.6",
|
||||
club=main_club,
|
||||
limit_age=18,
|
||||
)
|
||||
cble.save()
|
||||
cble.buying_groups.add(subscribers)
|
||||
cble.save()
|
||||
cons = Product(
|
||||
name="Consigne Eco-cup",
|
||||
code="CONS",
|
||||
@ -574,7 +590,6 @@ Welcome to the wiki page!
|
||||
special_selling_price="1",
|
||||
club=main_club,
|
||||
)
|
||||
cons.id = 1152
|
||||
cons.save()
|
||||
dcons = Product(
|
||||
name="Déconsigne Eco-cup",
|
||||
@ -585,9 +600,8 @@ Welcome to the wiki page!
|
||||
special_selling_price="-1",
|
||||
club=main_club,
|
||||
)
|
||||
dcons.id = 1151
|
||||
dcons.save()
|
||||
Product(
|
||||
cors = Product(
|
||||
name="Corsendonk",
|
||||
code="CORS",
|
||||
product_type=p,
|
||||
@ -595,8 +609,12 @@ Welcome to the wiki page!
|
||||
selling_price="1.7",
|
||||
special_selling_price="1.6",
|
||||
club=main_club,
|
||||
).save()
|
||||
Product(
|
||||
limit_age=18,
|
||||
)
|
||||
cors.save()
|
||||
cors.buying_groups.add(subscribers)
|
||||
cors.save()
|
||||
carolus = Product(
|
||||
name="Carolus",
|
||||
code="CARO",
|
||||
product_type=p,
|
||||
@ -604,7 +622,11 @@ Welcome to the wiki page!
|
||||
selling_price="1.7",
|
||||
special_selling_price="1.6",
|
||||
club=main_club,
|
||||
).save()
|
||||
limit_age=18,
|
||||
)
|
||||
carolus.save()
|
||||
carolus.buying_groups.add(subscribers)
|
||||
carolus.save()
|
||||
mde = Counter.objects.filter(name="MDE").first()
|
||||
mde.products.add(barb)
|
||||
mde.products.add(cble)
|
||||
|
@ -325,6 +325,13 @@ class User(AbstractBaseUser):
|
||||
)
|
||||
return s.exists()
|
||||
|
||||
@cached_property
|
||||
def account_balance(self):
|
||||
if hasattr(self, "customer"):
|
||||
return self.customer.amount
|
||||
else:
|
||||
return 0
|
||||
|
||||
_club_memberships = {}
|
||||
_group_names = {}
|
||||
_group_ids = {}
|
||||
@ -459,6 +466,23 @@ class User(AbstractBaseUser):
|
||||
def is_banned_counter(self):
|
||||
return self.is_in_group(settings.SITH_GROUP_BANNED_COUNTER_ID)
|
||||
|
||||
@cached_property
|
||||
def age(self) -> int:
|
||||
"""
|
||||
Return the age this user has the day the method is called.
|
||||
If the user has not filled his age, return 0
|
||||
"""
|
||||
if self.date_of_birth is None:
|
||||
return 0
|
||||
today = timezone.now()
|
||||
age = today.year - self.date_of_birth.year
|
||||
# remove a year if this year's birthday is yet to come
|
||||
age -= (today.month, today.day) < (
|
||||
self.date_of_birth.month,
|
||||
self.date_of_birth.day,
|
||||
)
|
||||
return age
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
create = False
|
||||
with transaction.atomic():
|
||||
|
5
core/static/core/js/alpinejs.min.js
vendored
Normal file
5
core/static/core/js/alpinejs.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -135,6 +135,10 @@ a {
|
||||
width: 23%;
|
||||
}
|
||||
|
||||
.clickable:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/*--------------------------------HEADER-------------------------------*/
|
||||
|
||||
#header_language_chooser {
|
||||
@ -159,9 +163,9 @@ a {
|
||||
|
||||
header {
|
||||
width: 90%;
|
||||
margin: 0px auto;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
box-shadow: $shadow-color 0px 0px 15px;
|
||||
box-shadow: $shadow-color 0 0 15px;
|
||||
border-top: none;
|
||||
background-color: $primary-neutral-dark-color;
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
@ -199,7 +203,7 @@ header {
|
||||
}
|
||||
|
||||
#header_connect_links {
|
||||
margin: 0.6em 0.6em 0em auto;
|
||||
margin: 0.6em 0.6em 0 auto;
|
||||
padding: 0.2em;
|
||||
color: $white-color;
|
||||
form {
|
||||
@ -226,7 +230,7 @@ header {
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
margin: 0em 1em;
|
||||
margin: 0 1em;
|
||||
font-weight: bold;
|
||||
color: $white-color;
|
||||
&:hover {
|
||||
@ -254,7 +258,7 @@ header {
|
||||
#header_search {
|
||||
display: inline-block;
|
||||
flex: auto;
|
||||
margin: 0.8em 0em;
|
||||
margin: 0.8em 0;
|
||||
input {
|
||||
width: 14ch;
|
||||
}
|
||||
@ -265,10 +269,10 @@ header {
|
||||
flex: initial;
|
||||
flex-wrap: wrap;
|
||||
text-align: right;
|
||||
margin: 0em;
|
||||
margin: 0;
|
||||
div {
|
||||
display: inline;
|
||||
padding: 1.2em 0em;
|
||||
padding: 1.2em 0;
|
||||
&:first-child {
|
||||
flex: auto;
|
||||
}
|
||||
@ -290,7 +294,7 @@ header {
|
||||
background: white;
|
||||
text-align: left;
|
||||
font-size: 80%;
|
||||
margin: 1.5em 0em 0em -14em;
|
||||
margin: 1.5em 0 0em -14em;
|
||||
.header_notif_date {
|
||||
font-weight: bold;
|
||||
}
|
||||
@ -298,7 +302,7 @@ header {
|
||||
color: grey;
|
||||
}
|
||||
a {
|
||||
margin: 0em;
|
||||
margin: 0;
|
||||
color: $black-color;
|
||||
&:hover {
|
||||
color: $primary-dark-color;
|
||||
@ -326,7 +330,7 @@ header {
|
||||
|
||||
#popupheader {
|
||||
width: 88%;
|
||||
margin: 0px auto;
|
||||
margin: 0 auto;
|
||||
padding: 0.3em 1%;
|
||||
}
|
||||
|
||||
@ -369,15 +373,15 @@ header {
|
||||
|
||||
#page {
|
||||
width: 90%;
|
||||
margin: 0em auto;
|
||||
/*---------------------------------NAV---------------------------------*/
|
||||
margin: 20px auto 0;
|
||||
/*---------------------------------NAV---------------------------------*/
|
||||
nav {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
background-color: $primary-dark-color;
|
||||
color: $white-color;
|
||||
border-radius: 6px 6px 0px 0px;
|
||||
box-shadow: $shadow-color 0px 0px 15px;
|
||||
border-radius: 6px 6px 0 0;
|
||||
box-shadow: $shadow-color 0 0 15px;
|
||||
|
||||
a {
|
||||
flex: auto;
|
||||
@ -392,10 +396,10 @@ header {
|
||||
background: $secondary-neutral-color;
|
||||
color: $white-color;
|
||||
&:first-of-type {
|
||||
border-radius: 6px 0px 0px 0px;
|
||||
border-radius: 6px 0 0 0;
|
||||
}
|
||||
&:last-of-type {
|
||||
border-radius: 0px 6px 0px 0px;
|
||||
border-radius: 0 6px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -418,7 +422,7 @@ header {
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
background-color: #f9f9f9;
|
||||
box-shadow: 3px 3px 3px 0px $shadow-color;
|
||||
box-shadow: 3px 3px 3px 0 $shadow-color;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@ -443,7 +447,7 @@ header {
|
||||
/*--------------------------------CONTENT------------------------------*/
|
||||
#quick_notif {
|
||||
width: 100%;
|
||||
margin: 0px auto;
|
||||
margin: 0 auto;
|
||||
list-style-type: none;
|
||||
background: $second-color;
|
||||
li {
|
||||
@ -454,11 +458,29 @@ header {
|
||||
|
||||
#content {
|
||||
padding: 1em 1%;
|
||||
box-shadow: $shadow-color 0px 5px 10px;
|
||||
box-shadow: $shadow-color 0 5px 10px;
|
||||
background: $white-color;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.alert {
|
||||
margin: 10px;
|
||||
border: #fc8181 1px solid;
|
||||
background-color: rgb(255,245,245);
|
||||
border-radius: 4px;
|
||||
color: #c53030;
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
max-width: 100%;
|
||||
align-items: center;
|
||||
text-align: justify;
|
||||
|
||||
.alert-main {
|
||||
flex: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.tool_bar {
|
||||
overflow: auto;
|
||||
padding: 4px;
|
||||
@ -499,7 +521,7 @@ header {
|
||||
flex-wrap: wrap;
|
||||
.news_column {
|
||||
display: inline-block;
|
||||
margin: 0px;
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
#news_admin {
|
||||
@ -540,7 +562,7 @@ header {
|
||||
margin-bottom: 1em;
|
||||
#agenda_title,#birthdays_title {
|
||||
margin: 0em;
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
border-radius: 5px 5px 0 0;
|
||||
box-shadow: $shadow-color 1px 1px 1px;
|
||||
padding: 0.5em;
|
||||
font-weight: bold;
|
||||
@ -609,10 +631,10 @@ header {
|
||||
font-weight: bold;
|
||||
font-family: monospace;
|
||||
font-size: 1.4em;
|
||||
border-radius: 7px 0px 0px 7px;
|
||||
border-radius: 7px 0 0 7px;
|
||||
|
||||
div {
|
||||
margin: 0px auto;
|
||||
margin: 0 auto;
|
||||
.day {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
@ -697,7 +719,7 @@ header {
|
||||
padding: 0.4em;
|
||||
padding-left: 1em;
|
||||
background: $secondary-neutral-light-color;
|
||||
box-shadow: $shadow-color 0px 0px 2px;
|
||||
box-shadow: $shadow-color 0 0 2px;
|
||||
border-radius: 18px 5px 18px 5px;
|
||||
h4 {
|
||||
margin: 0em;
|
||||
@ -1030,7 +1052,7 @@ h1, h2, h3, h4, h5, h6 {
|
||||
|
||||
h1 {
|
||||
font-size: 160%;
|
||||
margin-left: 0px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@ -1060,7 +1082,7 @@ h6 {
|
||||
|
||||
p, pre {
|
||||
margin-top: 0.8em;
|
||||
margin-left: 0px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
ul, ol, dl {
|
||||
@ -1118,7 +1140,7 @@ td {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
> ul {
|
||||
margin-top: 0px;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1471,7 +1493,7 @@ textarea {
|
||||
}
|
||||
|
||||
.search_bar {
|
||||
margin: 10px 0px;
|
||||
margin: 10px 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
height: 20p;
|
||||
@ -1487,7 +1509,7 @@ textarea {
|
||||
margin-top: 5px;
|
||||
background: $secondary-color;
|
||||
color: white;
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
border-radius: 10px 10px 0 0;
|
||||
.title {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
@ -1527,7 +1549,7 @@ textarea {
|
||||
text-align: center;
|
||||
img {
|
||||
max-width: 70%;
|
||||
margin: 0px auto;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1615,7 +1637,7 @@ footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
background-color: $primary-neutral-dark-color;
|
||||
box-shadow: $shadow-color 0px 0px 15px;
|
||||
box-shadow: $shadow-color 0 0 15px;
|
||||
a {
|
||||
padding: 0.8em;
|
||||
flex: 1;
|
||||
@ -1631,7 +1653,7 @@ footer {
|
||||
/*---------------------------------FORMS-------------------------------*/
|
||||
|
||||
form {
|
||||
margin: 0px auto;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
@ -1645,7 +1667,7 @@ label {
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-buttonpane {
|
||||
bottom: 0px;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
width: 97%;
|
||||
}
|
||||
@ -1690,8 +1712,8 @@ label {
|
||||
/*-------------------------------MARKDOWN------------------------------*/
|
||||
|
||||
.markdown {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
code {
|
||||
font-family: monospace;
|
||||
color: $white-color;
|
||||
@ -1722,7 +1744,7 @@ label {
|
||||
}
|
||||
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-top,
|
||||
.ui-corner-left {
|
||||
border-radius: 0px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
#club_detail {
|
||||
@ -1748,13 +1770,13 @@ $pedagogy-white-text: #f0f0f0;
|
||||
.pedagogy {
|
||||
&.star-not-checked {
|
||||
color : #f7f7f7;
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
&.star-checked {
|
||||
color: $pedagogy-orange;
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
&.grade-without-star {
|
||||
@ -2126,8 +2148,8 @@ $pedagogy-white-text: #f0f0f0;
|
||||
grid-area: markdown;
|
||||
|
||||
min-height: 139px;
|
||||
margin-top: 0px;
|
||||
margin-right: 0px;
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
padding: 10px;
|
||||
text-align: justify;
|
||||
overflow: auto;
|
||||
@ -2173,7 +2195,7 @@ $pedagogy-white-text: #f0f0f0;
|
||||
"report"
|
||||
"date"
|
||||
"author";
|
||||
margin-top: 0px;
|
||||
margin-top: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -2188,7 +2210,7 @@ $pedagogy-white-text: #f0f0f0;
|
||||
|
||||
@media screen and (max-width: $large-devices){
|
||||
clip-path: none;
|
||||
padding: 0px;
|
||||
padding: 0;
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
|
||||
|
191
core/static/eboutic/css/eboutic.css
Normal file
191
core/static/eboutic/css/eboutic.css
Normal file
@ -0,0 +1,191 @@
|
||||
#eboutic {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
align-items: flex-start;
|
||||
column-gap: 20px;
|
||||
margin: 0 20px 20px;
|
||||
}
|
||||
|
||||
#eboutic-title {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
#eboutic h3 {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#basket {
|
||||
min-width: 300px;
|
||||
border-radius: 8px;
|
||||
box-shadow: rgb(60 64 67 / 30%) 0 1px 3px 0, rgb(60 64 67 / 15%) 0 4px 8px 3px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#basket h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 765px) {
|
||||
#eboutic {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 10px;
|
||||
row-gap: 20px;
|
||||
}
|
||||
#eboutic-title {
|
||||
margin-bottom: 20px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
#basket {
|
||||
}
|
||||
}
|
||||
|
||||
#eboutic #basket .error-message {
|
||||
margin-top: 5px;
|
||||
background-color: #f8d7da;
|
||||
border: #f5c6cb 1px solid;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 7px;
|
||||
}
|
||||
#eboutic #basket .error-message p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#eboutic .item-list {
|
||||
margin-left: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#eboutic .item-list li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px
|
||||
}
|
||||
|
||||
#eboutic .item-name {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#eboutic .item-price, #eboutic .item-quantity {
|
||||
width: 65px;
|
||||
}
|
||||
|
||||
#eboutic .item-quantity {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#eboutic .fa-plus, #eboutic .fa-minus {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#eboutic .item-price {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* CSS du catalogue */
|
||||
|
||||
#eboutic #catalog {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
row-gap: 30px;
|
||||
}
|
||||
|
||||
#eboutic .category-header {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
#eboutic .product-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 15px;
|
||||
row-gap: 15px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 765px) {
|
||||
#eboutic #catalog {
|
||||
row-gap: 15px;
|
||||
}
|
||||
|
||||
#eboutic section {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#eboutic .product-group {
|
||||
justify-content: space-around;
|
||||
}
|
||||
}
|
||||
|
||||
#eboutic .product-button {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
min-width: 120px;
|
||||
max-width: 150px;
|
||||
padding: 10px;
|
||||
overflow: hidden;
|
||||
box-shadow: rgb(60 64 67 / 30%) 0 1px 3px 0, rgb(60 64 67 / 15%) 0 4px 8px 3px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
row-gap: 5px;
|
||||
}
|
||||
|
||||
#eboutic .product-button:active {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#eboutic .product-button img, #eboutic .product-button .fa {
|
||||
margin: 0;
|
||||
border-radius: 4px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
#eboutic .product-button p {
|
||||
font-size: 13px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#eboutic .catalog-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
column-gap: 30px;
|
||||
margin: 30px 0 0;
|
||||
}
|
||||
|
||||
#eboutic input {
|
||||
all: unset;
|
||||
}
|
||||
|
||||
#eboutic .catalog-buttons button {
|
||||
font-size: 15px;
|
||||
font-weight: normal;
|
||||
color: white;
|
||||
min-width: 60px;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
#eboutic .catalog-buttons .validate {
|
||||
background-color: #354a5f;
|
||||
}
|
||||
#eboutic .catalog-buttons .clear {
|
||||
background-color: gray;
|
||||
}
|
||||
#eboutic .catalog-buttons button i {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#eboutic .catalog-buttons button.validate:hover {
|
||||
background-color: #2c3646;
|
||||
}
|
||||
|
||||
#eboutic .catalog-buttons button.clear:hover {
|
||||
background-color:hsl(210,5%,30%);
|
||||
}
|
||||
|
||||
#eboutic .catalog-buttons form {
|
||||
margin: 0;
|
||||
}
|
104
core/static/eboutic/js/eboutic.js
Normal file
104
core/static/eboutic/js/eboutic.js
Normal file
@ -0,0 +1,104 @@
|
||||
function getCookie(name) {
|
||||
let cookieValue = null;
|
||||
if (document.cookie && document.cookie !== '') {
|
||||
const cookies = document.cookie.split(';');
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i].trim();
|
||||
// Does this cookie string begin with the name we want?
|
||||
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
|
||||
function get_starting_items() {
|
||||
const cookie = getCookie("basket_items")
|
||||
try {
|
||||
// django cookie backend does an utter mess on non-trivial data types
|
||||
// so we must perform a conversion of our own
|
||||
const biscuit = JSON.parse(JSON.parse(cookie.replace(/\\054/g, ',')));
|
||||
if (Array.isArray(biscuit)) {
|
||||
return biscuit;
|
||||
}
|
||||
return [];
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('alpine:init', () => {
|
||||
Alpine.data('basket', () => ({
|
||||
items: get_starting_items(),
|
||||
|
||||
get_total() {
|
||||
let total = 0;
|
||||
for (const item of this.items) {
|
||||
total += item["quantity"] * item["unit_price"];
|
||||
}
|
||||
return total;
|
||||
},
|
||||
|
||||
add(item) {
|
||||
item.quantity++;
|
||||
this.edit_cookies()
|
||||
},
|
||||
|
||||
remove(item_id) {
|
||||
const index = this.items.findIndex(e => e.id === item_id);
|
||||
if (index < 0) return;
|
||||
this.items[index].quantity -= 1;
|
||||
if (this.items[index].quantity === 0) {
|
||||
this.items = this.items.filter((e) => e.id !== this.items[index].id);
|
||||
}
|
||||
this.edit_cookies();
|
||||
},
|
||||
|
||||
clear_basket() {
|
||||
this.items = []
|
||||
this.edit_cookies();
|
||||
},
|
||||
|
||||
edit_cookies() {
|
||||
// a cookie survives an hour
|
||||
document.cookie = "basket_items=" + JSON.stringify(this.items) + ";Max-Age=3600";
|
||||
},
|
||||
|
||||
/**
|
||||
* Create an item in the basket if it was not already in
|
||||
* @param id : int the id of the product to add
|
||||
* @param name : String the name of the product
|
||||
* @param price : number the unit price of the product
|
||||
*/
|
||||
create_item(id, name, price) {
|
||||
let new_item = {
|
||||
id: id,
|
||||
name: name,
|
||||
quantity: 0,
|
||||
unit_price: price
|
||||
};
|
||||
this.items.push(new_item);
|
||||
this.add(new_item);
|
||||
},
|
||||
|
||||
/**
|
||||
* add an item to the basket.
|
||||
* This is called when the user click
|
||||
* on a button in the catalog (left side of the page)
|
||||
* @param id : int the id of the product to add
|
||||
* @param name : String the name of the product
|
||||
* @param price : number the unit price of the product
|
||||
*/
|
||||
add_from_catalog(id, name, price) {
|
||||
const item = this.items.find(e => e.id === id)
|
||||
if (item === undefined) {
|
||||
this.create_item(id, name, price);
|
||||
} else {
|
||||
// the user clicked on an item which is already in the basket
|
||||
this.add(item);
|
||||
}
|
||||
},
|
||||
}))
|
||||
})
|
@ -9,7 +9,10 @@
|
||||
<link rel="stylesheet" href="{{ static('core/jquery.datetimepicker.min.css') }}">
|
||||
<link rel="stylesheet" href="{{ static('ajax_select/css/ajax_select.css') }}">
|
||||
<link rel="stylesheet" href="{{ scss('core/style.scss') }}">
|
||||
<link rel="stylesheet" href="{{ static('core/js/ui/jquery-ui.min.css') }}">
|
||||
{% block jquery_css %}
|
||||
{# Thile file is quite heavy (around 250kb), so declaring it in a block allows easy removal #}
|
||||
<link rel="stylesheet" href="{{ static('core/js/ui/jquery-ui.min.css') }}">
|
||||
{% endblock %}
|
||||
<link rel="preload" as="style" href="{{ static('core/font-awesome/css/font-awesome.min.css') }}" onload="this.onload=null;this.rel='stylesheet'">
|
||||
<noscript><link rel="stylesheet" href="{{ static('core/font-awesome/css/font-awesome.min.css') }}"></noscript>
|
||||
<script defer href="{{ static('core/font-awesome/js/fontawesone.min.js') }}"></script>
|
||||
@ -18,6 +21,8 @@
|
||||
<script src="{{ static('core/js/jquery-3.1.0.min.js') }}"></script>
|
||||
<!-- Put here to always have acces to those functions on django widgets -->
|
||||
<script src="{{ static('core/js/script.js') }}"></script>
|
||||
{% block additional_css %}{% endblock %}
|
||||
{% block additional_js %}{% endblock %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
|
||||
@ -179,7 +184,9 @@
|
||||
</div>
|
||||
<a href="{{ url('forum:main') }}">{% trans %}Forum{% endtrans %}</a>
|
||||
<a href="{{ url('sas:main') }}">{% trans %}Gallery{% endtrans %}</a>
|
||||
<a href="{{ url('eboutic:main') }}">{% trans %}Eboutic{% endtrans %}</a>
|
||||
{% if request.user.is_authenticated %}
|
||||
<a href="{{ url('eboutic:main') }}">{% trans %}Eboutic{% endtrans %}</a>
|
||||
{% endif %}
|
||||
<div class="dropdown">
|
||||
<button class="dropbtn">{% trans %}Services{% endtrans %}
|
||||
<i class="fa fa-caret-down"></i>
|
||||
|
Reference in New Issue
Block a user