UI improvements and starts integration with SMS
- Lookup phone number in tekstemelding - Add simple card-number-membership should work - Simple card icon - More feedback
This commit is contained in:
1 parent
a0b9d444df
commit
4593e556b5
10 files changed
+237
-111
No files matched your search
@@ -19,8 +19,9 @@
|
||||
</div>
|
||||
{{ add_card_form|bootstrap }}
|
||||
<ul>
|
||||
<li>If no existing membership can be found, a new membership is registered.</li>
|
||||
<li>If an existing user is found, the membership is marked as renewed</li>
|
||||
<li>Registering a card number with a phone number already tied to an existing user, will add the card to that user.</li>
|
||||
<li>If no existing membership can be found, a new membership is registered (or renewed).</li>
|
||||
</ul>
|
||||
<button id="register-submit-btn" type="submit" class="btn btn-primary btn-lg" disabled>{% trans "Register card" %}</button>
|
||||
<button type="reset" class="register-reset-btn btn btn-default">{% trans "Reset" %}</button>
|
||||
|
||||
+5
-6
@@ -1,12 +1,11 @@
|
||||
from django.conf.urls import url
|
||||
from apps.kassa.views import register, inside_user_api, inside_phone_number_api, inside_card_number_api, \
|
||||
inside_register_api
|
||||
from apps.kassa.views import register, inside_user_api, inside_card_api, inside_register_api, \
|
||||
check_phone_number
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', register, name='register'),
|
||||
url(r'^inside/user/$', inside_user_api, name='inside-user-api'),
|
||||
url(r'^inside/phonenumber/$', inside_phone_number_api, name='inside-phone-number-api'),
|
||||
url(r'^inside/cardnumber/$', inside_card_number_api, name='inside-card-number-api'),
|
||||
url(r'^inside/register/$', inside_register_api, name='inside-register-api')
|
||||
|
||||
url(r'^check-phonenumber/$', check_phone_number, name='check-phone-number'),
|
||||
url(r'^inside/card/$', inside_card_api, name='inside-card-number-api'),
|
||||
url(r'^inside/register/$', inside_register_api, name='inside-register-api'),
|
||||
]
|
||||
+38
-9
@@ -6,6 +6,7 @@ from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import render
|
||||
import phonenumbers
|
||||
import requests
|
||||
|
||||
from apps.kassa.forms import AddCardForm, SearchUserForm
|
||||
@@ -32,21 +33,48 @@ def inside_user_api(request):
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
@login_required
|
||||
def inside_phone_number_api(request):
|
||||
@login_required()
|
||||
def check_phone_number(request):
|
||||
number = request.GET.get('phone_number', '').strip()
|
||||
|
||||
if len(number) < 2:
|
||||
return JsonResponse({'error': 'Phone number is too short'})
|
||||
|
||||
# Is phone number valid?
|
||||
try:
|
||||
p = phonenumbers.parse(number, 'NO')
|
||||
if not phonenumbers.is_valid_number(p):
|
||||
return JsonResponse({'error': "Phone number '{}' is invalid.".format(number)})
|
||||
except phonenumbers.NumberParseException as e:
|
||||
return JsonResponse({'error': str(e).replace('(1) ', '')})
|
||||
|
||||
number = phonenumbers.format_number(p, phonenumbers.PhoneNumberFormat.E164)
|
||||
|
||||
# Inside lookup existing user
|
||||
payload = {
|
||||
'apikey': settings.INSIDE_API_KEY,
|
||||
'q': request.GET.get('q', '')
|
||||
'q': number
|
||||
}
|
||||
url = '{}phonenumber.php'.format(settings.INSIDE_API_URL)
|
||||
data = requests.get(url, params=payload).json()
|
||||
inside_data = requests.get(url, params=payload).json()
|
||||
|
||||
return JsonResponse(data)
|
||||
# Tekstmelding lookup pending memberships
|
||||
payload = {
|
||||
'api_key': settings.TEKSTMELDING_API_KEY,
|
||||
'number': number
|
||||
}
|
||||
url = '{}kassa-pending-membership'.format(settings.TEKSTMELDING_API_URL)
|
||||
tekstmelding_data = requests.get(url, params=payload).json()
|
||||
|
||||
return JsonResponse({
|
||||
'tekstmelding': tekstmelding_data,
|
||||
'inside': inside_data
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
def inside_card_number_api(request):
|
||||
url = '{}cardnumber.php'.format(settings.INSIDE_API_URL)
|
||||
def inside_card_api(request):
|
||||
url = '{}card.php'.format(settings.INSIDE_API_URL)
|
||||
params = {
|
||||
'apikey': settings.INSIDE_API_KEY
|
||||
}
|
||||
@@ -55,9 +83,10 @@ def inside_card_number_api(request):
|
||||
post_data = json.loads(request.body)
|
||||
payload = {
|
||||
'card_number': post_data.get('card_number'),
|
||||
'user_id': post_data.get('user_id')
|
||||
'user_id': post_data.get('user_id'),
|
||||
'phone_number': post_data.get('phone_number'),
|
||||
'type': post_data.get('type') # renewal, new_user, new_card_only,
|
||||
}
|
||||
print payload
|
||||
response = requests.post(
|
||||
url,
|
||||
data=json.dumps(payload),
|
||||
|
||||
@@ -119,6 +119,9 @@ LOGIN_REDIRECT_URL = '/'
|
||||
INSIDE_API_KEY = ''
|
||||
INSIDE_API_URL = 'https://inside.studentersamfundet.no/api/'
|
||||
|
||||
TEKSTMELDING_API_KEY = ''
|
||||
TEKSTMELDING_API_URL = 'https://tekstmelding.neuf.no/'
|
||||
|
||||
# Local settings
|
||||
try:
|
||||
from local_settings import *
|
||||
|
||||
+85
-44
@@ -37,13 +37,25 @@ function update_user_with_card_details(user) {
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
function format_phone_number(str) {
|
||||
if(!str || str.length <= 1) {
|
||||
return 'No phone number';
|
||||
}
|
||||
if(str.length == 11) {
|
||||
return str.slice(0, 3) + " " + str.slice(3, 6) + " " + str.slice(6, 8) + " " + str.slice(8);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function format_results(results) {
|
||||
results = _.map(results, update_user_with_card_details);
|
||||
return nunjucksEnv.render('search_results.html', {'results': results});
|
||||
}
|
||||
function render_selected_user(user_data) {
|
||||
var context;
|
||||
if(user_data === undefined) {
|
||||
if(user_data === undefined || user_data === null) {
|
||||
context = {placeholder: true}; // dummy card
|
||||
} else {
|
||||
user_data = update_user_with_card_details(user_data);
|
||||
@@ -63,7 +75,7 @@ function set_toast(message, message_type) {
|
||||
_dom.toastWrap.addClass('visible');
|
||||
setTimeout(function() {
|
||||
_dom.toastWrap.removeClass('visible');
|
||||
}, 4000);
|
||||
}, 5000);
|
||||
}
|
||||
function set_selected_user(user, update_search_result) {
|
||||
selectedUser = user;
|
||||
@@ -230,42 +242,58 @@ $(document).ready(function(){
|
||||
};
|
||||
var urls = {
|
||||
insideUserApi: '/inside/user/',
|
||||
insidePhoneNumberApi: '/inside/phonenumber/',
|
||||
insideCardNumber: '/inside/cardnumber/',
|
||||
checkPhoneNumber: '/check-phonenumber/',
|
||||
insideCard: '/inside/card/',
|
||||
insideRegister: '/inside/register/'
|
||||
};
|
||||
/* Add filter |phoneNumber */
|
||||
nunjucksEnv.addFilter('phoneNumber', function(str) {
|
||||
if(!str || str.length <= 1) {
|
||||
return 'No phone number';
|
||||
}
|
||||
if(str.length == 11) {
|
||||
return str.slice(0, 3) + " " + str.slice(3, 6) + " " + str.slice(6, 8) + " " + str.slice(8);
|
||||
}
|
||||
|
||||
return str;
|
||||
});
|
||||
nunjucksEnv.addFilter('phoneNumber', format_phone_number);
|
||||
|
||||
/* Phone number as you type */
|
||||
function checkPhoneNumber() {
|
||||
var val = _dom.phoneNumberField.val().trim();
|
||||
$.getJSON(urls.checkPhoneNumber, {phone_number: val}, function(data) {
|
||||
if(data.error) {
|
||||
set_selected_user(null, true);
|
||||
set_field_state(_dom.phoneNumberField, 'error', data.error);
|
||||
return;
|
||||
}
|
||||
|
||||
var inside = data.inside;
|
||||
if(inside.users.length == 1) {
|
||||
/* Existing user */
|
||||
set_selected_user(inside.users[0], true);
|
||||
set_field_state(_dom.phoneNumberField, 'success', 'Phone number belongs to existing user.');
|
||||
cardForm.fields.phoneNumber = true;
|
||||
} else if(inside.card && inside.card.has_valid_membership) {
|
||||
var msg = 'Phone number is already tied to card '+ inside.card.card_number + ' and is valid until '+ inside.card.expires +'.';
|
||||
set_field_state(_dom.phoneNumberField, 'error', msg);
|
||||
cardForm.fields.phoneNumber = false;
|
||||
} else {
|
||||
set_selected_user(null, true);
|
||||
}
|
||||
|
||||
var tekstmelding = data.tekstmelding;
|
||||
if(tekstmelding.result !== null) {
|
||||
/* Pending SMS membership (not activated yet) */
|
||||
set_field_state(_dom.phoneNumberField, 'success', 'Phone number has pending membership (paid via SMS).');
|
||||
cardForm.fields.phoneNumber = true;
|
||||
}
|
||||
|
||||
update_submit_button();
|
||||
});
|
||||
}
|
||||
|
||||
var lazyCheckPhoneNumber = _.debounce(checkPhoneNumber, 250);
|
||||
_dom.phoneNumberField.on('input', function() {
|
||||
var val = _dom.phoneNumberField.val().trim();
|
||||
var validation_msg = validatePhoneNumber(val);
|
||||
if( validation_msg !== '') {
|
||||
set_selected_user(null, true);
|
||||
set_field_state(_dom.phoneNumberField, 'error', validation_msg);
|
||||
return;
|
||||
}
|
||||
$.getJSON(urls.insidePhoneNumberApi, {q: val}, function(data) {
|
||||
if(data.meta && data.meta.num_results == 1) {
|
||||
set_field_state(_dom.phoneNumberField, 'success');
|
||||
set_selected_user(data.results[0], true);
|
||||
} else {
|
||||
set_field_state(_dom.phoneNumberField, '');
|
||||
set_selected_user(null, true);
|
||||
}
|
||||
cardForm.fields.phoneNumber = true;
|
||||
update_submit_button();
|
||||
});
|
||||
|
||||
lazyCheckPhoneNumber();
|
||||
});
|
||||
/* Card number as you type */
|
||||
_dom.cardNumberField.on('input', function() {
|
||||
@@ -276,23 +304,28 @@ $(document).ready(function(){
|
||||
set_field_state(_dom.cardNumberField, 'error', validation_msg);
|
||||
return;
|
||||
}
|
||||
$.getJSON(urls.insideCardNumber, {card_number: val}, function(data) {
|
||||
$.getJSON(urls.insideCard, {card_number: val}, function(data) {
|
||||
if(data.error) {
|
||||
update_submit_button();
|
||||
cardForm.fields.cardNumber = false;
|
||||
set_field_state(_dom.cardNumberField, 'error', data.error);
|
||||
return;
|
||||
}
|
||||
if(!data.valid) {
|
||||
var card = data.card;
|
||||
var user = data.user;
|
||||
if(!card) {
|
||||
cardForm.fields.cardNumber = false;
|
||||
set_field_state(_dom.cardNumberField, 'error', 'Cannot find card number in database.');
|
||||
}
|
||||
else if(data.user !== null && data.valid) {
|
||||
var _user = data.user[0];
|
||||
else if(card && card.registered !== null) {
|
||||
var owner_string = 'phone number: '+ format_phone_number(card.owner_phone_number);
|
||||
if(user) {
|
||||
owner_string = 'existing user: ' + user.firstname + ' ' + user.lastname + ' (' + format_phone_number(user.number) + ')';
|
||||
}
|
||||
cardForm.fields.cardNumber = false;
|
||||
set_field_state(_dom.cardNumberField, 'error', 'Card number is in use and belongs to existing user: '+ _user.firstname +' '+ _user.lastname +' ('+_user.id+').');
|
||||
set_field_state(_dom.cardNumberField, 'error', 'Card number is in use and belongs to '+ owner_string +'.');
|
||||
}
|
||||
else if(data.user === null && data.valid) {
|
||||
else if(data.user === null && data.card) {
|
||||
cardForm.fields.cardNumber = true;
|
||||
set_field_state(_dom.cardNumberField, 'success');
|
||||
} else {
|
||||
@@ -352,21 +385,29 @@ $(document).ready(function(){
|
||||
e.preventDefault();
|
||||
// TODO on error output validation status
|
||||
// TODO on success:
|
||||
// - print what action was performed and suggest steps
|
||||
// - print suggested steps ("You will now get an sms with a link")
|
||||
// - show new user below form (hide/show after 10s)
|
||||
// - clear form
|
||||
|
||||
if( !cardFormIsValid() ) {
|
||||
// ERROR
|
||||
set_toast('Either phone number or card number is not valid', 'error');
|
||||
return;
|
||||
}
|
||||
var url = urls.insideRegister;
|
||||
var url = urls.insideCard;
|
||||
var payload = getFormData(_dom.registerCardForm);
|
||||
|
||||
/* Just updating card number? */
|
||||
if(payload.user_id && payload.card_number && selectedUser.is_member === "1") {
|
||||
url = urls.insideCardNumber;
|
||||
/* Register type */
|
||||
// FIXME: get from form
|
||||
if(selectedUser === null) {
|
||||
payload.type = 'new_card_only';
|
||||
} else {
|
||||
if(selectedUser.is_member === '1') {
|
||||
payload.type = 'renewal';
|
||||
} else {
|
||||
payload.type = 'new_user';
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax(url, {
|
||||
data: JSON.stringify(payload),
|
||||
contentType: 'application/json',
|
||||
@@ -379,18 +420,18 @@ $(document).ready(function(){
|
||||
|
||||
}).fail(function(data) {
|
||||
console.log("failed", data);
|
||||
set_toast('Failed!'+ data.error, 'error');
|
||||
var error_text = data.responseText;
|
||||
if(data.responseJSON) {
|
||||
error_text = data.responseJSON.error;
|
||||
}
|
||||
set_toast('Failed! '+ error_text, 'error');
|
||||
});
|
||||
});
|
||||
|
||||
/* On user id change */
|
||||
_dom.userIdField.on('change', function() {
|
||||
/* Render selected user in search form */
|
||||
if(selectedUser) {
|
||||
render_selected_user(selectedUser);
|
||||
return;
|
||||
}
|
||||
render_selected_user();
|
||||
render_selected_user(selectedUser);
|
||||
});
|
||||
/* Reset buttons */
|
||||
_dom.registerResetButton.on('click', function() {
|
||||
|
||||
@@ -19,6 +19,18 @@ input[type=number]::-webkit-inner-spin-button {
|
||||
input[type=number] {
|
||||
-moz-appearance:textfield;
|
||||
}
|
||||
.card-icon {
|
||||
display: inline-block;
|
||||
border-radius: 3px;
|
||||
padding: 0.45em 0.7em;
|
||||
background-color: #333;
|
||||
}
|
||||
.label-card-yes .card-icon {
|
||||
background-color: $green-color;
|
||||
}
|
||||
.label-card-no .card-icon {
|
||||
background-color: $red-color;
|
||||
}
|
||||
|
||||
/* Helpers */
|
||||
.center-block {
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
{% endif %}
|
||||
<!-- Card -->
|
||||
{% if res.card_number_active and res.card_is_legacy != '' %}
|
||||
<span class="label label-card label-card-yes"><span class="glyphicon glyphicon-ok"></span> {{ res.card_number_active }}</span>
|
||||
<span class="label label-card label-card-yes"><span class="card-icon"></span> {{ res.card_number_active }}</span>
|
||||
{% else %}
|
||||
<span class="label label-card label-card-no"><span class="glyphicon glyphicon-remove"></span> No card</span>
|
||||
<span class="label label-card label-card-no"><span class="card-icon"></span> No card</span>
|
||||
{% endif %}
|
||||
<!-- Is active -->
|
||||
{% if res.is_active == "1" %}
|
||||
@@ -52,7 +52,7 @@
|
||||
</div>
|
||||
<div class="phone-number"><span class="glyphicon glyphicon-phone"></span> {{ number|phoneNumber }}</div>
|
||||
<div class="labels">
|
||||
<span class="label label-card">New card</span>
|
||||
<span class="label label-card"><span class="card-icon"></span> New card</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
Vendored
+85
-44
@@ -37,13 +37,25 @@ function update_user_with_card_details(user) {
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
function format_phone_number(str) {
|
||||
if(!str || str.length <= 1) {
|
||||
return 'No phone number';
|
||||
}
|
||||
if(str.length == 11) {
|
||||
return str.slice(0, 3) + " " + str.slice(3, 6) + " " + str.slice(6, 8) + " " + str.slice(8);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function format_results(results) {
|
||||
results = _.map(results, update_user_with_card_details);
|
||||
return nunjucksEnv.render('search_results.html', {'results': results});
|
||||
}
|
||||
function render_selected_user(user_data) {
|
||||
var context;
|
||||
if(user_data === undefined) {
|
||||
if(user_data === undefined || user_data === null) {
|
||||
context = {placeholder: true}; // dummy card
|
||||
} else {
|
||||
user_data = update_user_with_card_details(user_data);
|
||||
@@ -63,7 +75,7 @@ function set_toast(message, message_type) {
|
||||
_dom.toastWrap.addClass('visible');
|
||||
setTimeout(function() {
|
||||
_dom.toastWrap.removeClass('visible');
|
||||
}, 4000);
|
||||
}, 5000);
|
||||
}
|
||||
function set_selected_user(user, update_search_result) {
|
||||
selectedUser = user;
|
||||
@@ -230,42 +242,58 @@ $(document).ready(function(){
|
||||
};
|
||||
var urls = {
|
||||
insideUserApi: '/inside/user/',
|
||||
insidePhoneNumberApi: '/inside/phonenumber/',
|
||||
insideCardNumber: '/inside/cardnumber/',
|
||||
checkPhoneNumber: '/check-phonenumber/',
|
||||
insideCard: '/inside/card/',
|
||||
insideRegister: '/inside/register/'
|
||||
};
|
||||
/* Add filter |phoneNumber */
|
||||
nunjucksEnv.addFilter('phoneNumber', function(str) {
|
||||
if(!str || str.length <= 1) {
|
||||
return 'No phone number';
|
||||
}
|
||||
if(str.length == 11) {
|
||||
return str.slice(0, 3) + " " + str.slice(3, 6) + " " + str.slice(6, 8) + " " + str.slice(8);
|
||||
}
|
||||
|
||||
return str;
|
||||
});
|
||||
nunjucksEnv.addFilter('phoneNumber', format_phone_number);
|
||||
|
||||
/* Phone number as you type */
|
||||
function checkPhoneNumber() {
|
||||
var val = _dom.phoneNumberField.val().trim();
|
||||
$.getJSON(urls.checkPhoneNumber, {phone_number: val}, function(data) {
|
||||
if(data.error) {
|
||||
set_selected_user(null, true);
|
||||
set_field_state(_dom.phoneNumberField, 'error', data.error);
|
||||
return;
|
||||
}
|
||||
|
||||
var inside = data.inside;
|
||||
if(inside.users.length == 1) {
|
||||
/* Existing user */
|
||||
set_selected_user(inside.users[0], true);
|
||||
set_field_state(_dom.phoneNumberField, 'success', 'Phone number belongs to existing user.');
|
||||
cardForm.fields.phoneNumber = true;
|
||||
} else if(inside.card && inside.card.has_valid_membership) {
|
||||
var msg = 'Phone number is already tied to card '+ inside.card.card_number + ' and is valid until '+ inside.card.expires +'.';
|
||||
set_field_state(_dom.phoneNumberField, 'error', msg);
|
||||
cardForm.fields.phoneNumber = false;
|
||||
} else {
|
||||
set_selected_user(null, true);
|
||||
}
|
||||
|
||||
var tekstmelding = data.tekstmelding;
|
||||
if(tekstmelding.result !== null) {
|
||||
/* Pending SMS membership (not activated yet) */
|
||||
set_field_state(_dom.phoneNumberField, 'success', 'Phone number has pending membership (paid via SMS).');
|
||||
cardForm.fields.phoneNumber = true;
|
||||
}
|
||||
|
||||
update_submit_button();
|
||||
});
|
||||
}
|
||||
|
||||
var lazyCheckPhoneNumber = _.debounce(checkPhoneNumber, 250);
|
||||
_dom.phoneNumberField.on('input', function() {
|
||||
var val = _dom.phoneNumberField.val().trim();
|
||||
var validation_msg = validatePhoneNumber(val);
|
||||
if( validation_msg !== '') {
|
||||
set_selected_user(null, true);
|
||||
set_field_state(_dom.phoneNumberField, 'error', validation_msg);
|
||||
return;
|
||||
}
|
||||
$.getJSON(urls.insidePhoneNumberApi, {q: val}, function(data) {
|
||||
if(data.meta && data.meta.num_results == 1) {
|
||||
set_field_state(_dom.phoneNumberField, 'success');
|
||||
set_selected_user(data.results[0], true);
|
||||
} else {
|
||||
set_field_state(_dom.phoneNumberField, '');
|
||||
set_selected_user(null, true);
|
||||
}
|
||||
cardForm.fields.phoneNumber = true;
|
||||
update_submit_button();
|
||||
});
|
||||
|
||||
lazyCheckPhoneNumber();
|
||||
});
|
||||
/* Card number as you type */
|
||||
_dom.cardNumberField.on('input', function() {
|
||||
@@ -276,23 +304,28 @@ $(document).ready(function(){
|
||||
set_field_state(_dom.cardNumberField, 'error', validation_msg);
|
||||
return;
|
||||
}
|
||||
$.getJSON(urls.insideCardNumber, {card_number: val}, function(data) {
|
||||
$.getJSON(urls.insideCard, {card_number: val}, function(data) {
|
||||
if(data.error) {
|
||||
update_submit_button();
|
||||
cardForm.fields.cardNumber = false;
|
||||
set_field_state(_dom.cardNumberField, 'error', data.error);
|
||||
return;
|
||||
}
|
||||
if(!data.valid) {
|
||||
var card = data.card;
|
||||
var user = data.user;
|
||||
if(!card) {
|
||||
cardForm.fields.cardNumber = false;
|
||||
set_field_state(_dom.cardNumberField, 'error', 'Cannot find card number in database.');
|
||||
}
|
||||
else if(data.user !== null && data.valid) {
|
||||
var _user = data.user[0];
|
||||
else if(card && card.registered !== null) {
|
||||
var owner_string = 'phone number: '+ format_phone_number(card.owner_phone_number);
|
||||
if(user) {
|
||||
owner_string = 'existing user: ' + user.firstname + ' ' + user.lastname + ' (' + format_phone_number(user.number) + ')';
|
||||
}
|
||||
cardForm.fields.cardNumber = false;
|
||||
set_field_state(_dom.cardNumberField, 'error', 'Card number is in use and belongs to existing user: '+ _user.firstname +' '+ _user.lastname +' ('+_user.id+').');
|
||||
set_field_state(_dom.cardNumberField, 'error', 'Card number is in use and belongs to '+ owner_string +'.');
|
||||
}
|
||||
else if(data.user === null && data.valid) {
|
||||
else if(data.user === null && data.card) {
|
||||
cardForm.fields.cardNumber = true;
|
||||
set_field_state(_dom.cardNumberField, 'success');
|
||||
} else {
|
||||
@@ -352,21 +385,29 @@ $(document).ready(function(){
|
||||
e.preventDefault();
|
||||
// TODO on error output validation status
|
||||
// TODO on success:
|
||||
// - print what action was performed and suggest steps
|
||||
// - print suggested steps ("You will now get an sms with a link")
|
||||
// - show new user below form (hide/show after 10s)
|
||||
// - clear form
|
||||
|
||||
if( !cardFormIsValid() ) {
|
||||
// ERROR
|
||||
set_toast('Either phone number or card number is not valid', 'error');
|
||||
return;
|
||||
}
|
||||
var url = urls.insideRegister;
|
||||
var url = urls.insideCard;
|
||||
var payload = getFormData(_dom.registerCardForm);
|
||||
|
||||
/* Just updating card number? */
|
||||
if(payload.user_id && payload.card_number && selectedUser.is_member === "1") {
|
||||
url = urls.insideCardNumber;
|
||||
/* Register type */
|
||||
// FIXME: get from form
|
||||
if(selectedUser === null) {
|
||||
payload.type = 'new_card_only';
|
||||
} else {
|
||||
if(selectedUser.is_member === '1') {
|
||||
payload.type = 'renewal';
|
||||
} else {
|
||||
payload.type = 'new_user';
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax(url, {
|
||||
data: JSON.stringify(payload),
|
||||
contentType: 'application/json',
|
||||
@@ -379,18 +420,18 @@ $(document).ready(function(){
|
||||
|
||||
}).fail(function(data) {
|
||||
console.log("failed", data);
|
||||
set_toast('Failed!'+ data.error, 'error');
|
||||
var error_text = data.responseText;
|
||||
if(data.responseJSON) {
|
||||
error_text = data.responseJSON.error;
|
||||
}
|
||||
set_toast('Failed! '+ error_text, 'error');
|
||||
});
|
||||
});
|
||||
|
||||
/* On user id change */
|
||||
_dom.userIdField.on('change', function() {
|
||||
/* Render selected user in search form */
|
||||
if(selectedUser) {
|
||||
render_selected_user(selectedUser);
|
||||
return;
|
||||
}
|
||||
render_selected_user();
|
||||
render_selected_user(selectedUser);
|
||||
});
|
||||
/* Reset buttons */
|
||||
_dom.registerResetButton.on('click', function() {
|
||||
|
||||
Vendored
+3
-3
@@ -54,13 +54,13 @@ output += "</span>\n ";
|
||||
}
|
||||
output += "\n <!-- Card -->\n ";
|
||||
if(runtime.memberLookup((runtime.contextOrFrameLookup(context, frame, "res")),"card_number_active", env.opts.autoescape) && runtime.memberLookup((runtime.contextOrFrameLookup(context, frame, "res")),"card_is_legacy", env.opts.autoescape) != "") {
|
||||
output += "\n <span class=\"label label-card label-card-yes\"><span class=\"glyphicon glyphicon-ok\"></span> ";
|
||||
output += "\n <span class=\"label label-card label-card-yes\"><span class=\"card-icon\"></span> ";
|
||||
output += runtime.suppressValue(runtime.memberLookup((runtime.contextOrFrameLookup(context, frame, "res")),"card_number_active", env.opts.autoescape), env.opts.autoescape);
|
||||
output += "</span>\n ";
|
||||
;
|
||||
}
|
||||
else {
|
||||
output += "\n <span class=\"label label-card label-card-no\"><span class=\"glyphicon glyphicon-remove\"></span> No card</span>\n ";
|
||||
output += "\n <span class=\"label label-card label-card-no\"><span class=\"card-icon\"></span> No card</span>\n ";
|
||||
;
|
||||
}
|
||||
output += "\n <!-- Is active -->\n ";
|
||||
@@ -86,7 +86,7 @@ output += "\n </label>\n";
|
||||
else {
|
||||
output += "\n <!-- Placeholder -->\n <div class=\"list-group-item search-result placeholder\">\n <div class=\"name\">\n <input type=\"radio\" name=\"user\" checked>\n <span class=\"glyphicon glyphicon-user\"></span> <em>New member</em>\n </div>\n <div class=\"phone-number\"><span class=\"glyphicon glyphicon-phone\"></span> ";
|
||||
output += runtime.suppressValue(env.getFilter("phoneNumber").call(context, runtime.contextOrFrameLookup(context, frame, "number")), env.opts.autoescape);
|
||||
output += "</div>\n <div class=\"labels\">\n <span class=\"label label-card\">New card</span>\n </div>\n </div>\n";
|
||||
output += "</div>\n <div class=\"labels\">\n <span class=\"label label-card\"><span class=\"card-icon\"></span> New card</span>\n </div>\n </div>\n";
|
||||
;
|
||||
}
|
||||
cb(null, output);
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}hr{box-sizing:content-box;height:0}pre{overflow:auto}samp{font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*,*:before,*:after{background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href)")"}abbr[title]:after{content:" (" attr(title)")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url("../fonts/glyphicons-halflings-regular.eot");src:url("../fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"),url("../fonts/glyphicons-halflings-regular.woff2") format("woff2"),url("../fonts/glyphicons-halflings-regular.woff") format("woff"),url("../fonts/glyphicons-halflings-regular.ttf") format("truetype"),url("../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.gLine truncated
|
||||
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}hr{box-sizing:content-box;height:0}pre{overflow:auto}samp{font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*,*:before,*:after{background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href)")"}abbr[title]:after{content:" (" attr(title)")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url("../fonts/glyphicons-halflings-regular.eot");src:url("../fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"),url("../fonts/glyphicons-halflings-regular.woff2") format("woff2"),url("../fonts/glyphicons-halflings-regular.woff") format("woff"),url("../fonts/glyphicons-halflings-regular.ttf") format("truetype"),url("../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.gLine truncated
|
||||
Reference in new issue
Block a user