Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/AAISS/AAISS-2023 into fro…
Browse files Browse the repository at this point in the history
…nt/feature/filter-workshop
  • Loading branch information
mr-amirfazel committed Nov 27, 2023
2 parents f3470ce + ef3f271 commit 5cec451
Show file tree
Hide file tree
Showing 20 changed files with 498 additions and 231 deletions.
18 changes: 18 additions & 0 deletions backend/backend_api/migrations/0050_presentation_has_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.4 on 2023-11-27 20:33

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("backend_api", "0049_alter_payment_id"),
]

operations = [
migrations.AddField(
model_name="presentation",
name="has_project",
field=models.BooleanField(default=False),
),
]
3 changes: 2 additions & 1 deletion backend/backend_api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ class Presentation(models.Model):
year = models.IntegerField(blank=False, default=2020)
cost = models.PositiveIntegerField(default=0)
capacity = models.PositiveIntegerField(default=50)

has_project = models.BooleanField(default=False, blank=False)

NOT_ASSIGNED = 'NOT_ASSIGNED'
ELEMENTARY = 'Elementary'
INTERMEDIATE = 'Intermediate'
Expand Down
2 changes: 1 addition & 1 deletion backend/backend_api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,5 @@ def __init__(self, *args, **kwargs):
path('', include(committee_routes)),
path('', include(user_route)),
path('payment/', views.PaymentViewSet.as_view({'post': 'payment'})),
path('payment/verify/', views.PaymentViewSet.as_view({'get': 'verify'})),
path('payment/verify/', views.PaymentViewSet.as_view({'post': 'verify'})),
]
11 changes: 6 additions & 5 deletions backend/backend_api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ class PaymentViewSet(viewsets.GenericViewSet):
@action(methods=['POST'], detail=False, permission_classes=[IsAuthenticated])
def payment(self, request):
account = request.user
call_back = request.data.get('call_back')
try:
user = User.objects.get(account=account)
except ObjectDoesNotExist:
Expand All @@ -223,7 +224,7 @@ def payment(self, request):

payment = Payment.create_payment_for_user(user)
response = ZIFYRequest().create_payment(str(payment.pk), payment.amount, user.name, user.phone_number,
user.account.email)
user.account.email, call_back)
if response['status'] == ZIFY_STATUS_OK:
payment.track_id = response['data']['order']
payment.save()
Expand All @@ -233,9 +234,9 @@ def payment(self, request):
return Response(
new_detailed_response(response['status'], response["message"]))

@action(methods=['GET'], detail=False)
@action(methods=['POST'], detail=False)
def verify(self, request):
pid = request.GET.get('clientrefid')
pid = request.data.get('clientrefid')
if pid is None:
return Response(new_detailed_response(
status.HTTP_400_BAD_REQUEST, "clientrefid is required"))
Expand All @@ -248,11 +249,11 @@ def verify(self, request):
if response['status'] == ZIFY_STATUS_OK:
payment.update_payment_status(Payment.PaymentStatus.PAYMENT_CONFIRMED)
# FIXME: redirect to payment success page
return Response(new_detailed_response(status.HTTP_200_OK, "Payment verified successfully"))
return Response(new_detailed_response(status.HTTP_200_OK, "Payment verified successfully", payment.pk))
else:
payment.update_payment_status(Payment.PaymentStatus.PAYMENT_REJECTED)
return Response(
new_detailed_response(response['status'], response["message"]))
new_detailed_response(response['status'], response["message"], payment.pk))


class StaffViewSet(viewsets.GenericViewSet,
Expand Down
5 changes: 2 additions & 3 deletions backend/payment_backends/zify.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
ZIFY_STATUS_BAN = 403
ZIFY_STATUS_NOT_FOUND = 404
ZIFY_PAYMENT_DESCRIPTION = 'register workshops or talks'
ZIFY_CALL_BACK = 'https://aaiss.ir/api/payment/verify/'
ZIFY_URL = "https://zify.ir/api/order/v2/create"
ZIFY_URL_VERIFY = "https://zify.ir/api/order/v2/verify"
ZIFY_PAYMENT_LINK = 'https://zify.ir/order/accept/{track_id}'
Expand All @@ -30,7 +29,7 @@ def __init__(self):
def get_order_url(track_id: str):
return ZIFY_PAYMENT_LINK.format(track_id=track_id)

def create_payment(self, order_id, amount, user_name, user_phone, user_email):
def create_payment(self, order_id, amount, user_name, user_phone, user_email, call_back):
body = {
"payer": {
"first_name": "",
Expand All @@ -54,7 +53,7 @@ def create_payment(self, order_id, amount, user_name, user_phone, user_email):
"description": ZIFY_PAYMENT_DESCRIPTION
}
],
"returnUrl": ZIFY_CALL_BACK,
"returnUrl": call_back,
"clientRefId": order_id,
"shipping_total": 0,
"off_total": 0,
Expand Down
1 change: 1 addition & 0 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import './App.css';
import './App-mobile.css';
import './css/Nav.css';
import './css/Theme.css';
import './css/callback-page.css'

import React from 'react';
import { BrowserRouter } from 'react-router-dom';
Expand Down
10 changes: 6 additions & 4 deletions frontend/src/components/item-card/item-card.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Button, Card, CardActions, CardContent, CardHeader, Chip, Divider, Stac
import PropTypes from 'prop-types';
import MoreInfoModal from './more-info-modal';

const Presenter = ({ presenterName }) => (
export const Presenter = ({ presenterName }) => (
<Stack flexDirection="row" alignItems="center" gap={1}>
<Person />
<Typography variant="body1" sx={{ fontSize: 14 }} color="text.secondary">
Expand All @@ -13,8 +13,7 @@ const Presenter = ({ presenterName }) => (
</Stack>
);

// TODO: format cost with commas
const Cost = ({ cost }) => (
export const Cost = ({ cost }) => (
<Stack flexDirection="row" alignItems="center" gap={1}>
<CreditCard />
<Typography variant="overline" sx={{ fontSize: 14 }} color="text.secondary">
Expand Down Expand Up @@ -43,7 +42,7 @@ const Level = ({ name, color }) => (
</Stack>
);

const levelComponentMapping = {
export const levelComponentMapping = {
Elementary: <Level name="elementary" color="success.light" />,
Intermediate: <Level name="intermediate" color="secondary.main" />,
Advanced: <Level name="advanced" color="warning.light" />,
Expand Down Expand Up @@ -106,7 +105,10 @@ const ItemCard = ({
visibility={moreInfoModalVisibility}
onVisibilityChange={() => setMoreInfoModalVisibility(false)}
title={title}
presenterName={presenterName}
cost={cost}
purchaseState={purchaseState}
level={level}
hasProject={hasProject}
prerequisites={prerequisites}
syllabus={syllabus}
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/components/item-card/more-info-modal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
Chip,
} from '@mui/material';
import PropTypes from 'prop-types';
import { Cost, levelComponentMapping, Presenter } from './item-card';

const Prerequisites = ({ prerequisites }) => (
<>
Expand Down Expand Up @@ -42,6 +43,9 @@ const MoreInfoModal = ({
visibility,
onVisibilityChange,
title,
presenterName,
cost,
level,
purchaseState,
hasProject,
prerequisites,
Expand All @@ -68,6 +72,10 @@ const MoreInfoModal = ({
>
<DialogTitle variant="h5">{title}</DialogTitle>
<DialogContent>
<Presenter presenterName={presenterName} />
{levelComponentMapping[level]}
<Cost cost={cost} />
<Divider sx={{ my: 2 }} />
<Prerequisites prerequisites={prerequisites} />
<Divider sx={{ my: 2 }} />
<Syllabus syllabus={syllabus} />
Expand Down Expand Up @@ -96,6 +104,9 @@ const MoreInfoModal = ({

MoreInfoModal.propTypes = {
title: PropTypes.string,
presenterName: PropTypes.string,
cost: PropTypes.number,
level: PropTypes.string,
isBought: PropTypes.bool,
purchaseState: PropTypes.number,
prerequisites: PropTypes.string,
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/css/callback-page.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.back-to-home-container {
background-color: var(--background-color-lighter-40);
}

.back-to-home {
color: var(--light-text-color);
}
87 changes: 40 additions & 47 deletions frontend/src/pages/Signup/Signup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,19 @@ const SignUpForm = ({ onLoginClick }) => {
navigate(ROUTES.myAccount);
};

// const handleSignUp = useCallback(() => {
// const data = {};
// data.name = fullname;
// data.phone_number = phoneNumber;
// data.account = {
// password: password,
// email: email,
// };
// createUser(data);
// }, [createUser, email, fullname, password, phoneNumber]);
const handleSignUp = useCallback(() => {
const data = {};
data.name = fullname;
data.phone_number = phoneNumber;
data.account = {
password: password,
email: email,
};
createUser(data);
}, [createUser, email, fullname, password, phoneNumber]);

// TODO: add form validation
const handleFormSubmit = async (e) => {
console.log('handle form submit');
const handleFormSubmit = (e) => {
e.preventDefault();
if (hasEmailError(email)) {
setIsEmailWrong(true);
Expand All @@ -84,42 +83,33 @@ const SignUpForm = ({ onLoginClick }) => {
setSecondPassHelperText('Passwords are not the same');
return;
}

// API call
const data = {
name: fullname,
phone_number: phoneNumber,
account: {
password: password,
email: email,
},
};
createUser(data);
// TODO: route to my-account page
};

useEffect(() => {
if (createUserData == null) return;

const toastDataTemp = {};
if (createUserData) {
switch (createUserData.status) {
case 200:
case 201:
toastDataTemp.message = 'Account Created Successfully! Please Check Your Email.';
toastDataTemp.alertType = 'success';
navToMyAccountPage();
break;
case 400:
toastDataTemp.message = 'User with This Email Already Exists!';
toastDataTemp.alertType = 'error';
break;
default:
toastDataTemp.message = 'Unexpected Error! Please Try Again Later.';
toastDataTemp.alertType = 'error';
break;
}
setAccessTokenFromLocalStorage();
setToastData(toastDataTemp);
setOpenToast(true);
switch (createUserData.status) {
case 200:
case 201:
toastDataTemp.message = 'Account Created Successfully! Please Check Your Email.';
toastDataTemp.alertType = 'success';
navToMyAccountPage();
break;
case 400:
toastDataTemp.message = 'User with This Email Already Exists!';
toastDataTemp.alertType = 'error';
break;
default:
toastDataTemp.message = 'Unexpected Error! Please Try Again Later.';
toastDataTemp.alertType = 'error';
break;
}

setAccessTokenFromLocalStorage();
setToastData(toastDataTemp);
setOpenToast(true);
}, [createUserData]);

return (
Expand Down Expand Up @@ -195,7 +185,7 @@ const SignUpForm = ({ onLoginClick }) => {
}}
/>
<Stack gap={2}>
<Button color="primary" variant="contained" type="submit">
<Button onClick={handleSignUp} color="primary" variant="contained" type="submit">
SignUp
</Button>
<Button color="primary" variant="outlined" onClick={onLoginClick}>
Expand Down Expand Up @@ -234,9 +224,11 @@ const LoginForm = ({ onSignUpClick }) => {
// TODO: route to my-account page if it's successful
};

const { navigate } = useNavigate();
const {navigate} = useNavigate()
const { issueToken, issueTokenResponse } = useAPI();
const { setAccessTokenFromLocalStorage } = useConfig();
const {
setAccessTokenFromLocalStorage
} = useConfig()

useEffect(() => {
if (issueTokenResponse == null) return;
Expand All @@ -245,7 +237,8 @@ const LoginForm = ({ onSignUpClick }) => {
setOpenToast(true);

localStorage['user'] = JSON.stringify(issueTokenResponse.data);
setAccessTokenFromLocalStorage();
setAccessTokenFromLocalStorage()

}, [issueTokenResponse]);

const handleClickOnForgotPass = () => {
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/pages/my-account/MyAccount.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import useMyAccount from './useMyAccount.js';
const TAB_ITEMS = ['Workshops', 'Presentations', 'Cart'];

const MyAccount = () => {
const { talks, workshops, cart, removeFromCartHandler, toastData, openToast, setOpenToast } = useMyAccount();
const { talks, workshops, handleBuyCart, cart, removeFromCartHandler, toastData, openToast, setOpenToast } = useMyAccount();
const [tabValue, setTabValue] = useState(TAB_ITEMS[0]);

const handleChangeTab = (event, newValue) => {
Expand Down Expand Up @@ -60,7 +60,8 @@ const MyAccount = () => {
};

const List = ({ type, items }) => {
return items?.map((item, index) => (
if (items == null) return;
return items.map((item, index) => (
<ItemCard
key={index}
isWorkshop={type === 'Workshops'}
Expand Down Expand Up @@ -119,7 +120,7 @@ const MyAccount = () => {
<Divider sx={{ my: 2 }} />
<Stack alignItems="center" gap={1}>
<Typography>Total: {calculateTotalCost()} T</Typography>
<Button variant="contained" sx={{ px: 4 }} disabled={calculateTotalCost() === 0}>
<Button onClick={handleBuyCart} variant="contained" sx={{ px: 4 }} disabled={calculateTotalCost() === 0}>
Buy
</Button>
</Stack>
Expand Down
Loading

0 comments on commit 5cec451

Please sign in to comment.