diff --git a/api/v1/serializers/user.py b/api/v1/serializers/user.py index 3903a66d..a05957db 100644 --- a/api/v1/serializers/user.py +++ b/api/v1/serializers/user.py @@ -45,6 +45,7 @@ class UserSerializer(DynamicFieldsMixin, serializers.ModelSerializer): 'balance', 'show_in_mainpage', 'trial_lesson', + 'review_url', ) read_only_fields = ( diff --git a/api/v1/urls.py b/api/v1/urls.py index 07baaaf1..2ed7195b 100644 --- a/api/v1/urls.py +++ b/api/v1/urls.py @@ -18,7 +18,7 @@ from .views import ( UserViewSet, LessonViewSet, ImageObjectViewSet, SchoolScheduleViewSet, LiveLessonViewSet, PaymentViewSet, ObjectCommentsViewSet, - ContestViewSet, ContestWorkViewSet, + ContestViewSet, ContestWorkViewSet, NotifiedAboutBonuses, AuthorBalanceUsersViewSet, CaptureEmail, FAQViewSet, UserGalleryViewSet, BonusesViewSet) router = DefaultRouter() @@ -64,6 +64,7 @@ schema_view = get_schema_view( ) urlpatterns = [ + path('notified-about-bonuses/', NotifiedAboutBonuses.as_view(), name='notified-about-bonuses'), path('capture-email/', CaptureEmail.as_view(), name='capture-email'), path('author-balance-users/', AuthorBalanceUsersViewSet.as_view(), name='author-balance-users'), path('api-token-auth/', ObtainToken.as_view(), name='api-token-auth'), diff --git a/api/v1/views.py b/api/v1/views.py index f43ca18a..47a507ee 100644 --- a/api/v1/views.py +++ b/api/v1/views.py @@ -9,9 +9,9 @@ from rest_framework.decorators import (detail_route, list_route, action, permission_classes, authentication_classes as auth_classes) from rest_framework.response import Response from rest_framework.settings import api_settings +from django.utils.timezone import now from . import ExtendedModelViewSet, BothListFormatMixin - from .serializers.config import ConfigSerializer from .serializers.course import ( CategorySerializer, LikeSerializer, @@ -432,6 +432,16 @@ class UserViewSet(ExtendedModelViewSet): # 'delete': IsAdmin, # } + def update(self, *args, **kwargs): + response = super().update(*args, **kwargs) + instance = self.get_object() + + if instance.review_url and not instance.bonuses.filter(is_service=True, + action_name=UserBonus.ACTION_HAVE_REVIEW).count(): + UserBonus.objects.create(user=instance, amount=UserBonus.AMOUNT_HAVE_REVIEW, is_service=True, + action_name=UserBonus.ACTION_HAVE_REVIEW) + return response + def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) @@ -738,3 +748,16 @@ class BonusesViewSet(BothListFormatMixin, ExtendedModelViewSet): 'referral__referral__first_name', 'referral__referral__last_name', ) + + +class NotifiedAboutBonuses(views.APIView): + authentication_classes = () + + def post(self, request): + #FIXME + user = User.objects.get(pk=request.data.get('user')) + for b in user.bonuses.filter(notified_at__isnull=True): + b.notified_at = now() + b.save() + return Response({'status': 'ok'}) + diff --git a/apps/payment/migrations/0033_userbonus_notified_at.py b/apps/payment/migrations/0033_userbonus_notified_at.py new file mode 100644 index 00000000..9804bcb0 --- /dev/null +++ b/apps/payment/migrations/0033_userbonus_notified_at.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.7 on 2019-03-27 20:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('payment', '0032_auto_20190207_1233'), + ] + + operations = [ + migrations.AddField( + model_name='userbonus', + name='notified_at', + field=models.DateTimeField(blank=True, null=True), + ), + ] diff --git a/apps/payment/migrations/0034_auto_20190327_2055.py b/apps/payment/migrations/0034_auto_20190327_2055.py new file mode 100644 index 00000000..00ec22f5 --- /dev/null +++ b/apps/payment/migrations/0034_auto_20190327_2055.py @@ -0,0 +1,22 @@ +# Generated by Django 2.0.7 on 2019-03-27 20:55 + +from django.utils import timezone +from django.db import migrations + + +def fill_bonuses_notified_at(apps, schema_editor): + UserBonus = apps.get_model('payment', 'UserBonus') + for ub in UserBonus.objects.filter(notified_at__isnull=True): + ub.notified_at = timezone.now() + ub.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('payment', '0033_userbonus_notified_at'), + ] + + operations = [ + migrations.RunPython(fill_bonuses_notified_at), + ] diff --git a/apps/payment/migrations/0035_auto_20190405_1828.py b/apps/payment/migrations/0035_auto_20190405_1828.py new file mode 100644 index 00000000..55ff4230 --- /dev/null +++ b/apps/payment/migrations/0035_auto_20190405_1828.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.7 on 2019-04-05 18:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('payment', '0034_auto_20190327_2055'), + ] + + operations = [ + migrations.AlterField( + model_name='userbonus', + name='action_name', + field=models.CharField(blank=True, default='', max_length=20), + ), + ] diff --git a/apps/payment/models.py b/apps/payment/models.py index 4e157d4a..a7f0d463 100644 --- a/apps/payment/models.py +++ b/apps/payment/models.py @@ -1,4 +1,3 @@ -from decimal import Decimal import arrow import short_url from django.db.models import Func, F @@ -14,7 +13,6 @@ from django.core.validators import RegexValidator from django.utils.timezone import now from django.conf import settings -from apps.content.models import ImageObject from project.utils import weekdays_in_date_range from apps.course.models import Course @@ -249,6 +247,11 @@ class Payment(PolymorphicModel): if created: from apps.notification.tasks import send_gift_certificate send_gift_certificate(ugs.id) + # Если это не первая покупка, - отправляем бонусы юзеру + if self.user.paid_one_more and not self.user.bonuses.filter( + is_service=True, action_name=UserBonus.ACTION_PAID_ONE_MORE).count(): + UserBonus.objects.create(user=self.user, amount=UserBonus.AMOUNT_PAID_ONE_MORE, is_service=True, + action_name=UserBonus.ACTION_PAID_ONE_MORE) # Если юзер реферал и нет платежа, где применялась скидка if hasattr(self.user, 'referral') and not self.user.referral.payment: # Платеж - как сигнал, что скидка применилась @@ -299,13 +302,23 @@ class GiftCertificatePayment(Payment): class UserBonus(models.Model): + ACTION_FILL_PROFILE = 'fill_profile' + ACTION_PAID_ONE_MORE = 'paid_one_more' + ACTION_HAVE_REVIEW = 'have_review' + ACTION_CHILD_BIRTHDAY = 'child_birthday' + AMOUNT_FILL_PROFILE = 50 + AMOUNT_PAID_ONE_MORE = 100 + AMOUNT_HAVE_REVIEW = 300 + AMOUNT_CHILD_BIRTHDAY = 200 + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='bonuses') amount = models.DecimalField(max_digits=8, decimal_places=2, default=0) payment = models.ForeignKey(Payment, on_delete=models.SET_NULL, null=True) referral = models.ForeignKey('user.Referral', on_delete=models.SET_NULL, null=True) created_at = models.DateTimeField(auto_now_add=True) is_service = models.BooleanField(default=False) - action_name = models.CharField(max_length=10, blank=True, default='') + action_name = models.CharField(max_length=20, blank=True, default='') + notified_at = models.DateTimeField(blank=True, null=True) class Meta: ordering = ('created_at',) diff --git a/apps/payment/tests/__init__.py b/apps/payment/tests/__init__.py new file mode 100644 index 00000000..40a96afc --- /dev/null +++ b/apps/payment/tests/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/apps/payment/tests.py b/apps/payment/tests/tests_models.py similarity index 100% rename from apps/payment/tests.py rename to apps/payment/tests/tests_models.py diff --git a/apps/user/migrations/0031_user_review_url.py b/apps/user/migrations/0031_user_review_url.py new file mode 100644 index 00000000..abac92e9 --- /dev/null +++ b/apps/user/migrations/0031_user_review_url.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.7 on 2019-04-04 18:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('user', '0030_auto_20190318_1320'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='review_url', + field=models.URLField(blank=True, default='', verbose_name='Ссылка на видеоотзыв'), + ), + ] diff --git a/apps/user/models.py b/apps/user/models.py index 87d43490..aca57b23 100644 --- a/apps/user/models.py +++ b/apps/user/models.py @@ -94,6 +94,7 @@ class User(AbstractUser): child_gender = models.CharField( 'Пол ребенка', max_length=1, default='n', choices=GENDER_CHOICES) child_birthday = models.DateField('День рождения ребенка', null=True, blank=True) + review_url = models.URLField('Ссылка на видеоотзыв', blank=True, default='') objects = UserManager() @@ -138,6 +139,22 @@ class User(AbstractUser): Q(payment__isnull=False, payment__status__in=Payment.PW_PAID_STATUSES) | Q(is_service=True), ).aggregate(models.Sum('amount')).get('amount__sum') or 0) + @property + def has_new_bonuses(self): + from apps.payment.models import Payment + last_bonus = self.bonuses.filter( + Q(payment__isnull=False, payment__status__in=Payment.PW_PAID_STATUSES) | Q(is_service=True), + ).order_by('-created_at').first() + return bool(last_bonus) and not last_bonus.notified_at + + @property + def paid_one_more(self): + from apps.payment.models import SchoolPayment, CoursePayment, Payment + school_payments_cnt = SchoolPayment.objects.filter(status__in=Payment.PW_PAID_STATUSES, user=self, + add_days=False).count() + course_payment_cnt = CoursePayment.objects.filter(status__in=Payment.PW_PAID_STATUSES, user=self).count() + return school_payments_cnt > 1 or course_payment_cnt > 1 or (school_payments_cnt and course_payment_cnt) + @receiver(post_save, sender=User) def create_auth_token(sender, instance=None, created=False, **kwargs): diff --git a/apps/user/templates/user/bonus-history.html b/apps/user/templates/user/bonus-history.html index ef3bf9d8..211bf9f5 100644 --- a/apps/user/templates/user/bonus-history.html +++ b/apps/user/templates/user/bonus-history.html @@ -3,7 +3,6 @@ {% load rupluralize from plural %} {% block content %} -
@@ -12,24 +11,82 @@ 1 LIL = 1 ₽
-
- Приглашайте друзей в Lil School и получайте {{ config.REFERRER_BONUS }}% - от суммы их первой покупки. Накапливайте монеты и тратьте их на оплату школы и курсов. -
- Просто отправьте эту ссылку, по которой ваши друзья могут присоединиться к нам: +
+
+
Приглашайте друзей в Lil School
+
+ Получайте {{ config.REFERRER_BONUS }}% от суммы их первой покупки. +
+ Просто отправьте эту ссылку, по которой ваши друзья могут присоединиться к нам: +
+
+
+ + +
+
+
+
+ +
+
+
+
-
-
-
- - +
+
Как еще заработать лилики?
+
+ Накапливайте монеты и тратьте их на оплату школы и курсов. Около трети наших учеников обучаются за счет лиликов. +
+ +
+
+
1
+
+
Заполнить профиль
+ Заполните свой профиль, включая номер телефона. +
+
+50 LIL
+ +
{% if request.user.phone and request.user.first_name and request.user.last_name %} + {% endif %}
+
+
+
2
+
+
Оплата второго месяца или курса
+ Получайте бонусы при оплате последующий месяцев обучения или курсов. Чем большевы с нами, чем больше Лиликов вы получаете. +
+
+100 LIL
+ +
{% if request.user.paid_one_more %}{% endif %}
+
+
+
3
+
+
Видео-отзыв о Lil School
+ Выкладывайте свои видео-обзоры и видео-отзывы в Инстаграм с тегом @Lil.School #LilSchool и высылаете отчет на почту school@lil.city +
+
+100 LIL
+ +
{% if request.user.review_url %}{% endif %}
+
+
+
4
+
+
На День Рождения!
+ Мы любим наших учеников, поэтому дарим лилики на день рождения. +
+
+200 LIL
+ +
{% if request.user.child_first_name and request.user.child_last_name and request.user.child_birthday %} + {% endif %}
- {% include 'templates/blocks/share.html' with share_object_name="ссылкой" share_url=referrer_url share_tw_title=share_text share_tg_text=share_text %}
diff --git a/apps/user/templates/user/profile-settings.html b/apps/user/templates/user/profile-settings.html index 2f3a4b66..0ac4bc7d 100644 --- a/apps/user/templates/user/profile-settings.html +++ b/apps/user/templates/user/profile-settings.html @@ -152,7 +152,7 @@
-
Телефон
+
НОМЕР ТЕЛЕФОНА РОДИТЕЛЯ
diff --git a/apps/user/views.py b/apps/user/views.py index 1c244b01..e2571acc 100644 --- a/apps/user/views.py +++ b/apps/user/views.py @@ -24,7 +24,7 @@ from apps.config.models import Config from apps.course.models import Course from apps.notification.utils import send_email from apps.school.models import SchoolSchedule -from apps.payment.models import AuthorBalance, CoursePayment, SchoolPayment, Payment, UserGiftCertificate +from apps.payment.models import AuthorBalance, CoursePayment, SchoolPayment, Payment, UserGiftCertificate, UserBonus from apps.user.models import AuthorRequest, EmailSubscription, SubscriptionCategory from .forms import AuthorRequesForm, UserEditForm, WithdrawalForm @@ -245,7 +245,14 @@ class ProfileEditView(UpdateView): else: messages.error(request, 'Неверный пароль.') messages.info(request, 'Данные сохранены.') - return super().post(request, *args, **kwargs) + response = super().post(request, *args, **kwargs) + user = User.objects.get(pk=request.user.id) + # начисляемм бонусы, если заполнил профиль + if user.phone and user.first_name and user.last_name and not user.bonuses.filter( + is_service=True, action_name=UserBonus.ACTION_FILL_PROFILE).count(): + UserBonus.objects.create(user=user, amount=UserBonus.AMOUNT_FILL_PROFILE, is_service=True, + action_name=UserBonus.ACTION_FILL_PROFILE) + return response def get_success_url(self): return reverse('user-edit-profile') diff --git a/project/templates/blocks/lil_store_js.html b/project/templates/blocks/lil_store_js.html index cc334c94..67cd6d2c 100644 --- a/project/templates/blocks/lil_store_js.html +++ b/project/templates/blocks/lil_store_js.html @@ -17,6 +17,8 @@ id: '{{ request.user.id|default:'' }}', role: +'{{ request.user.role }}', photo: '{% if request.user.photo %}{{ request.user.photo.url }}{% else %}{% static 'img/user_default.jpg' %}{% endif %}', + hasNewBonuses: {{ request.user.has_new_bonuses|yesno:"true,false" }}, + bonus: +'{{ request.user.bonus }}', }, components: {}, urls: { diff --git a/project/templates/blocks/popup_bonuses_came.html b/project/templates/blocks/popup_bonuses_came.html new file mode 100644 index 00000000..2c2415a5 --- /dev/null +++ b/project/templates/blocks/popup_bonuses_came.html @@ -0,0 +1,19 @@ +{% load static %} + diff --git a/project/templates/blocks/user_menu.html b/project/templates/blocks/user_menu.html index efc3171c..955d3583 100644 --- a/project/templates/blocks/user_menu.html +++ b/project/templates/blocks/user_menu.html @@ -4,6 +4,7 @@ diff --git a/project/templates/lilcity/index.html b/project/templates/lilcity/index.html index 1e406194..4c228b4e 100644 --- a/project/templates/lilcity/index.html +++ b/project/templates/lilcity/index.html @@ -48,6 +48,7 @@ {% include "templates/blocks/popup_course_lock.html" %} {% include "templates/blocks/popup_subscribe.html" %} {% include "templates/blocks/popup_capture_email.html" %} + {% include "templates/blocks/popup_bonuses_came.html" %}
{% include 'templates/blocks/lil_store_js.html' %} {% block pre_app_js %}{% endblock pre_app_js %} diff --git a/project/tests/test_features.py b/project/tests/test_features.py new file mode 100644 index 00000000..dba636a6 --- /dev/null +++ b/project/tests/test_features.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +import json + +from datetime import timedelta + +from django.test import TestCase +from django.utils.timezone import now +from django.shortcuts import reverse +from factory.faker import Faker + +from project.tests.factories import UserFactory, CourseFactory +from apps.payment.models import CoursePayment, SchoolPayment, UserBonus, Payment +from apps.user.models import User + + +class AutoAddingUserBonusTestCase(TestCase): + + def test_adding_user_bonuses_after_paid_more_one(self): + user = UserFactory.create(role=User.USER_ROLE, first_name='', last_name='', phone='') + course = CourseFactory.create(price=1000) + course2 = CourseFactory.create(price=1000) + self.assertEqual(user.bonus, 0, 'При создании есть бонусы') + + cp = CoursePayment.objects.create(user=user, course=course, access_expire=now() + timedelta(100)) + cp.status = Payment.PW_PAID_STATUSES[0] + cp.save() + del user.__dict__['bonus'] + self.assertEqual(user.bonus, 0, 'Есть бонусы после покупки 1 курса') + + cp2 = CoursePayment.objects.create(user=user, course=course2, access_expire=now() + timedelta(100)) + cp2.status = Payment.PW_PAID_STATUSES[0] + cp2.save() + del user.__dict__['bonus'] + self.assertEqual(user.bonus, UserBonus.AMOUNT_PAID_ONE_MORE, 'Неверное кол-во бонусов после покупки 2 курсов') + + cp.delete() + del user.__dict__['bonus'] + self.assertEqual(user.bonus, UserBonus.AMOUNT_PAID_ONE_MORE, 'Изменились бонусы после удаления оплаты 1 курса') + + user.bonuses.all().delete() + sp = SchoolPayment.objects.create(user=user, weekdays=[1, 2, 3], add_days=False, date_start=now().date(), + date_end=(now() + timedelta(30)).date(), amount=1000, status=Payment.PW_PAID_STATUSES[0]) + del user.__dict__['bonus'] + self.assertEqual(user.bonus, UserBonus.AMOUNT_PAID_ONE_MORE, 'Неверное кол-во бонусов после покупки курса и школы') + + user.bonuses.all().delete() + cp2.delete() + sp2 = SchoolPayment.objects.create(user=user, weekdays=[1, 2, 3], add_days=False, date_start=(now() + timedelta(31)).date(), + date_end=(now() + timedelta(60)).date(), amount=1000, status=Payment.PW_PAID_STATUSES[0]) + del user.__dict__['bonus'] + self.assertEqual(user.bonus, UserBonus.AMOUNT_PAID_ONE_MORE, 'Неверное кол-во бонусов после покупки 2 месяцев школы') + + User.objects.all().delete() + CoursePayment.objects.all().delete() + SchoolPayment.objects.all().delete() + UserBonus.objects.all().delete() + + def test_adding_user_bonuses_after_fill_profile(self): + user = UserFactory.create(role=User.USER_ROLE, first_name='', last_name='', phone='') + self.assertEqual(user.bonus, 0, 'При создании есть бонусы') + self.client.force_login(user) + data = {k: user.__dict__[k] for k in ['email', 'slug', 'child_first_name', + 'child_last_name', 'child_birthday', 'child_gender', 'city', + 'country', 'birthday', 'gender', 'about', 'instagram', 'facebook', + 'twitter', 'pinterest', 'youtube', 'vkontakte', 'site']} + + data.update({ + 'first_name': Faker('first_name').generate({}), + 'last_name': Faker('last_name').generate({}), + 'phone': '+79123456789', + 'old_password': '', + 'new_password1': '', + 'new_password2': '', + }) + for k, v in data.items(): + if v is None: + data[k] = '' + self.client.post(reverse('user-edit-profile'), data) + + del user.__dict__['bonus'] + self.assertEqual(user.bonus, UserBonus.AMOUNT_FILL_PROFILE, 'Неверное кол-во бонусов после заполнения профиля') + + User.objects.all().delete() + UserBonus.objects.all().delete() + + def test_adding_user_bonuses_after_fill_review_url(self): + user = UserFactory.create(role=User.USER_ROLE, first_name='', last_name='', phone='') + self.assertEqual(user.bonus, 0, 'При создании есть бонусы') + self.client.force_login(user) + self.client.patch('/api/v1/users/%d/' % user.id, json.dumps({ + 'review_url': 'http://youtube.com/review_url', + }), 'application/json') + del user.__dict__['bonus'] + self.assertEqual(user.bonus, UserBonus.AMOUNT_HAVE_REVIEW, 'Неверное кол-во бонусов после заполнения ссылки на отзыв') + + User.objects.all().delete() + UserBonus.objects.all().delete() diff --git a/web/package.json b/web/package.json index 1c128202..eaa18164 100755 --- a/web/package.json +++ b/web/package.json @@ -39,6 +39,7 @@ "axios": "^0.17.1", "babel-polyfill": "^6.26.0", "baguettebox.js": "^1.10.0", + "bowser": "^2.1.2", "clipboard": "^2.0.1", "downscale": "^1.0.4", "extract-loader": "^3.1.0", diff --git a/web/src/fonts/ProximaNova-Bold.otf b/web/src/fonts/ProximaNova-Bold.otf new file mode 100644 index 00000000..4df9e171 Binary files /dev/null and b/web/src/fonts/ProximaNova-Bold.otf differ diff --git a/web/src/img/done2.png b/web/src/img/done2.png new file mode 100644 index 00000000..4bc9f7b2 Binary files /dev/null and b/web/src/img/done2.png differ diff --git a/web/src/img/lilcoin48x54.png b/web/src/img/lilcoin48x54.png new file mode 100644 index 00000000..961dbcde Binary files /dev/null and b/web/src/img/lilcoin48x54.png differ diff --git a/web/src/img/lilcoin_salut.gif b/web/src/img/lilcoin_salut.gif new file mode 100644 index 00000000..350b46db Binary files /dev/null and b/web/src/img/lilcoin_salut.gif differ diff --git a/web/src/img/lilcoin_spin.gif b/web/src/img/lilcoin_spin.gif new file mode 100644 index 00000000..b164de1b Binary files /dev/null and b/web/src/img/lilcoin_spin.gif differ diff --git a/web/src/img/lils.png b/web/src/img/lils.png new file mode 100644 index 00000000..122ec6f3 Binary files /dev/null and b/web/src/img/lils.png differ diff --git a/web/src/js/modules/popup.js b/web/src/js/modules/popup.js index 8d3079ba..864f5312 100644 --- a/web/src/js/modules/popup.js +++ b/web/src/js/modules/popup.js @@ -4,7 +4,8 @@ import {api} from './api'; import "modal-video/js/jquery-modal-video.js"; import "modal-video/css/modal-video.min.css"; import {email as emailValid} from 'vuelidate/lib/validators'; -import Cookies from 'js-cookie' +import Cookies from 'js-cookie'; +import Bowser from "bowser"; moment.locale('ru'); @@ -303,6 +304,55 @@ $(document).ready(function () { showPopup(); } + if(window.LIL_STORE.user.id && window.LIL_STORE.user.hasNewBonuses && window.LIL_STORE.user.bonus > 0){ + $(document).ready(() => { + popup = $('.js-popup-bonuses-came'); + const $bonusesImg = popup.find('.bonuses-came__img'); + const $bonusesValue = popup.find('.bonuses-came__bonuses'); + showPopup(); + const audioAddition = new Audio(); + const audioSalut = new Audio(); + audioAddition.preload = 'auto'; + audioSalut.preload = 'auto'; + const browser = Bowser.parse(window.navigator.userAgent).browser.name.toLowerCase(); + if(browser.indexOf("firefox") > -1 || browser.indexOf("opera") > -1){ + audioAddition.src = window.LIL_STORE.staticUrl + 'sounds/Lil_World_Addition.ogg'; + audioSalut.src = window.LIL_STORE.staticUrl + 'sounds/Lil_World_Jingle_08.ogg'; + } + else{ + audioAddition.src = window.LIL_STORE.staticUrl + 'sounds/Lil_World_Addition.mp3'; + audioSalut.src = window.LIL_STORE.staticUrl + 'sounds/Lil_World_Jingle_08.mp3'; + } + audioAddition.play().catch(error => console.log(error)); + $bonusesImg.attr('src', window.LIL_STORE.staticUrl + 'img/lilcoin48x54.png') + .attr('src', window.LIL_STORE.staticUrl + 'img/lilcoin_spin.gif'); + $({bonuses: 0}).animate({bonuses: window.LIL_STORE.user.bonus}, { + duration: 2900, + easing: "linear", + step: function(val) { + $bonusesValue.html(Math.ceil(val)); + } + }); + api.post('/api/v1/notified-about-bonuses/', { + user: window.LIL_STORE.user.id + }); + popup.find('.js-popup-close').click(() => { + hidePopup().then(() => { + const $salut = $('.header__lil-coin-img-salut'); + const $lilcoin = $('.header__lil-coin-img'); + $lilcoin.animate({opacity: 0}, 200); + $salut.attr('src', '').attr('src', window.LIL_STORE.staticUrl + 'img/lilcoin_salut.gif') + .animate({opacity: 100}, 200); + audioSalut.play(); + setTimeout(() => { + $salut.animate({opacity: 0}, 500); + $lilcoin.animate({opacity: 100}, 500); + }, 2000); + }); + }) + }); + } + function showPopup(){ if(! popup && popupName){ popup = $(popupName); diff --git a/web/src/sass/_common.sass b/web/src/sass/_common.sass index 70e754e6..a735c24a 100755 --- a/web/src/sass/_common.sass +++ b/web/src/sass/_common.sass @@ -653,6 +653,12 @@ a.btn color: rgba(25, 25, 25, 0.3) &__lil-coin-img margin-bottom: -5px + &__lil-coin-img-salut + position: absolute + height: 65px + left: -9px + top: -15px + opacity: 0 .main display: flex @@ -4457,18 +4463,35 @@ a .referrer-url display: flex + + +m + flex-direction: column + + &__text-column + flex: 50% + padding-right: 16% + padding-top: 8px + + +m + padding-right: 0 + + &__title + font-size: 20px + margin-bottom: 5px + + &__url-column + display: flex + flex-direction: column + flex: 30% + align-items: center + &__input - width: auto height: 40px - border: 1px solid #D1FF7F - padding: 8px - border-radius: 3px 0 0 3px - border-right: none + width: 100% + margin-bottom: 5px - &:focus - border: 1px solid #D1FF7F &__btn - border-radius: 0 3px 3px 0 + width: 100% .bonuses @@ -4557,3 +4580,63 @@ a margin-top: -20px color: #333333 font-size: 12px + + +.bonuses-table + margin-left: -120px + margin-top: 50px + margin-right: -46px + + &__row + display: flex + width: 100% + margin-bottom: 35px + + & > div + font-size: 14px + + & > div:nth-child(1) + flex: 115px + font-size: 40px + margin-top: -7px + text-align: center + & > div:nth-child(2) + flex: 320px + & > div:nth-child(3) + flex: 165px + font-size: 20px + font-weight: bold + text-align: center + & > div:nth-child(4) + flex: 220px + + & .btn + width: 100% + + & > div:nth-child(5) + flex: 40px + padding-top: 13px + padding-left: 10px + text-align: center + + &__title + margin-bottom: 5px + font-size: 20px + + +.bonuses-came + &__body + padding: 30px 30px 50px + text-align: center + + &__title + margin-bottom: 5px + margin-top: 5px + font-size: 25px + + &__bonuses + font-size: 50px + margin-bottom: -8px + + &__text + margin: 40px 0 diff --git a/web/src/sounds/Lil_World_Addition.mp3 b/web/src/sounds/Lil_World_Addition.mp3 new file mode 100644 index 00000000..08ab17da Binary files /dev/null and b/web/src/sounds/Lil_World_Addition.mp3 differ diff --git a/web/src/sounds/Lil_World_Addition.ogg b/web/src/sounds/Lil_World_Addition.ogg new file mode 100644 index 00000000..213f467f Binary files /dev/null and b/web/src/sounds/Lil_World_Addition.ogg differ diff --git a/web/src/sounds/Lil_World_Jingle_08.mp3 b/web/src/sounds/Lil_World_Jingle_08.mp3 new file mode 100644 index 00000000..7ab9a3f3 Binary files /dev/null and b/web/src/sounds/Lil_World_Jingle_08.mp3 differ diff --git a/web/src/sounds/Lil_World_Jingle_08.ogg b/web/src/sounds/Lil_World_Jingle_08.ogg new file mode 100644 index 00000000..9bcad431 Binary files /dev/null and b/web/src/sounds/Lil_World_Jingle_08.ogg differ diff --git a/web/webpack.config.js b/web/webpack.config.js index ddda36cd..08ac624e 100644 --- a/web/webpack.config.js +++ b/web/webpack.config.js @@ -22,6 +22,7 @@ module.exports = { imagesGiftCertificates: glob('./src/img/gift-certificates/*'), imagesReviews: glob('./src/img/reviews/*'), fonts: glob('./src/fonts/*'), + sounds: glob('./src/sounds/*'), }, output: { path: path.join(__dirname, "build"), @@ -118,6 +119,10 @@ module.exports = { { test: /\.(ttf|otf|eot|woff(2)?)(\?[a-z0-9]+)?$/, loader: 'file-loader?name=[name].[ext]' + }, + { + test: /\.(mp3|wav|ogg)$/, + loader: 'file-loader?name=[name].[ext]&outputPath=./sounds/' } ] },