Skip to content

Commit

Permalink
Merge pull request #13 from HiEventsDev/develop
Browse files Browse the repository at this point in the history
Fix quantity validation bug + i18n
  • Loading branch information
daveearley committed Jun 6, 2024
2 parents f61896f + fbbc6e9 commit 96f5fac
Show file tree
Hide file tree
Showing 33 changed files with 1,078 additions and 953 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@

</div>

<div align="center">
🌟 A star would be much appreciated! 🌟
</div>

<hr/>

## Table of Contents
Expand Down Expand Up @@ -93,7 +97,7 @@ a quick start, follow these steps:
cd hi.events/docker/all-in-one
```

3. **Run the set-up script:**
3. **Start the Docker Containers:**
```bash
docker-compose up -d
```
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Http/Request/User/CreateUserRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class CreateUserRequest extends BaseRequest
public function rules(): array
{
return [
'first_name' => 'required|min:2',
'last_name' => 'required|min:2',
'first_name' => 'required|min:1',
'last_name' => 'required|min:1',
'role' => Rule::in(Role::valuesArray()),
'email' => [
'required',
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Http/Request/User/UpdateMeRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class UpdateMeRequest extends BaseRequest
public function rules(): array
{
return [
'first_name' => 'required_without_all:current_password,password,password_confirmation|min:2',
'last_name' => 'required_without_all:current_password,password,password_confirmation|min:2',
'first_name' => 'required_without_all:current_password,password,password_confirmation|min:1',
'last_name' => 'required_without_all:current_password,password,password_confirmation|min:1',
'email' => 'required_without_all:current_password,password,password_confirmation|email',
'timezone' => 'required_without_all:current_password,password,password_confirmation|timezone',

Expand Down
2 changes: 2 additions & 0 deletions backend/app/Repository/Eloquent/TicketRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public function getQuantityRemainingForTicketPrice(int $ticketId, int $ticketPri
WHERE order_items.ticket_price_id = :ticketPriceId
AND orders.status in ('RESERVED')
AND current_timestamp < orders.reserved_until
AND orders.deleted_at IS NULL
AND order_items.deleted_at IS NULL
), 0)
) AS quantity_remaining,
ticket_prices.initial_quantity_available IS NULL AS unlimited_tickets_available
Expand Down
1 change: 0 additions & 1 deletion backend/app/Resources/Account/AccountResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public function toArray(Request $request): array
return [
'id' => $this->getId(),
'name' => $this->getName(),
'email' => $this->getEmail(),
'currency_code' => $this->getCurrencyCode(),
'timezone' => $this->getTimezone(),
'updated_at' => $this->getUpdatedAt(),
Expand Down
3 changes: 2 additions & 1 deletion backend/app/Resources/Ticket/TicketResourcePublic.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function toArray(Request $request): array
'is_before_sale_start_date' => $this->isBeforeSaleStartDate(),
'is_after_sale_end_date' => $this->isAfterSaleEndDate(),
'price' => $this->when(
(bool)$this->getTicketPrices() && !$this->isTieredType(),
$this->getTicketPrices() && !$this->isTieredType(),
fn() => $this->getPrice(),
),
'prices' => $this->when(
Expand All @@ -40,6 +40,7 @@ public function toArray(Request $request): array
),
$this->mergeWhen((bool)$this->getTicketPrices(), fn() => [
'is_available' => $this->isAvailable(),
'is_sold_out' => $this->isSoldOut(),
]),
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,23 @@ private function validateTicketQuantity(int $ticketIndex, array $ticketAndQuanti
$totalQuantity = collect($ticketAndQuantities['quantities'])->sum('quantity');
$maxPerOrder = (int)$ticket->getMaxPerOrder() ?: 100; // Placeholder for config value
$minPerOrder = (int)$ticket->getMinPerOrder() ?: 1;
$ticketQuantityAvailable = $this->ticketRepository->getQuantityRemainingForTicketPrice(
ticketId: $ticket->getId(),
ticketPriceId: $ticketAndQuantities['quantities'][0]['price_id']
);

if ($totalQuantity > $ticketQuantityAvailable) {
throw ValidationException::withMessages([
"tickets.$ticketIndex" => __("The maximum number of tickets available for :ticket is :max", [
'max' => $ticketQuantityAvailable,
'ticket' => $ticket->getTitle(),
]),
]);
}

if ($totalQuantity > $maxPerOrder) {
throw ValidationException::withMessages([
"tickets.$ticketIndex" => __("The maximum numbers number of tickets for :tickets is :max", [
"tickets.$ticketIndex" => __("The maximum number of tickets available for :tickets is :max", [
'max' => $maxPerOrder,
'ticket' => $ticket->getTitle(),
]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

Your password has been reset for your account on {{ config('app.name') }}.

If you did not request a password reset, please let us know.
If you did not request a password reset, please immediately contact reset your password.

Thank you
</x-mail::message>
2 changes: 1 addition & 1 deletion docker/development/docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ services:
build:
context: ./../../frontend
dockerfile: Dockerfile.ssr.dev
container_name: frontend-ssr
container_name: frontend
ports:
- "5678:5678"
- "24678:24678"
Expand Down
4 changes: 2 additions & 2 deletions docker/development/start-dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ done

echo -e "\n${GREEN}Database is ready. Proceeding with migrations...${NC}"

if [ ! -f ./../backend/.env ]; then
if [ ! -f ./../../backend/.env ]; then
$COMPOSE_CMD exec backend cp .env.example .env
fi

if [ ! -f ./../frontend/.env ]; then
if [ ! -f ./../../frontend/.env ]; then
$COMPOSE_CMD exec frontend cp .env.example .env
fi

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/forms/QuestionForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export const QuestionForm = ({form, tickets}: QuestionFormProps) => {
icon: <IconCircleCheck/>,
label: t`Radio Option`,
value: QuestionType.RADIO,
description: t`A Radio option allows has multiple options but only one can be selected.`,
description: t`A Radio option has multiple options but only one can be selected.`,
},
{
icon: <IconSelector/>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const AccountSettings = () => {
name: '',
currency_code: '',
timezone: '',
email: '',
}
});
const accountQuery = useGetAccount();
Expand Down Expand Up @@ -57,20 +56,13 @@ const AccountSettings = () => {
<Card className={classes.tabContent}>
<LoadingMask/>
<fieldset disabled={updateMutation.isLoading || accountQuery.isLoading || !isUserAdmin}>
<form onSubmit={form.onSubmit(handleSubmit)}>
<form onSubmit={form.onSubmit(handleSubmit as any)}>
<TextInput
{...form.getInputProps('name')}
label={t`Account Name`}
placeholder={t`Name`}
description={t`Your account name is used on event pages and in emails.`}
/>
<TextInput
type={'email'}
{...form.getInputProps('email')}
label={t`Account Email`}
placeholder={t`Email`}
description={t`Your account email in outgoing emails.`}
/>
<Select
searchable
data={Object.entries(currencies).map(([key, value]) => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@ import {Anchor, Button, Group} from "@mantine/core";
import {StripeConnectDetails} from "../../../../../../types.ts";
import paymentClasses from "./PaymentSettings.module.scss"
import classes from "../../ManageAccount.module.scss"
import {useEffect, useState} from "react";

const ConnectStatus = (props: { stripeDetails: StripeConnectDetails }) => {
const isReturn = window?.location.search.includes('is_return');
const isRefresh = window?.location.search.includes('is_refresh');
const isReturningFromStripe = isReturn || isRefresh;
const [isReturningFromStripe, setIsReturningFromStripe] = useState(false);

useEffect(() => {
if (typeof window === 'undefined') {
return;
}
setIsReturningFromStripe(
window.location.search.includes('is_return') || window.location.search.includes('is_refresh')
);
}, []);

return (
<div className={paymentClasses.stripeInfo}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.header {
text-align: center;
margin-bottom: 30px;

h2 {
margin: 0;
}

p {
margin-top: -0;
}
}
32 changes: 20 additions & 12 deletions frontend/src/components/routes/auth/ResetPassword/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {ResetPasswordRequest} from "../../../../types.ts";
import {useFormErrorResponseHandler} from "../../../../hooks/useFormErrorResponseHandler.tsx";
import {t} from "@lingui/macro";
import {Card} from "../../../common/Card";
import classes from "./ResetPassword.module.scss";

export const ResetPassword = () => {
const form = useForm({
Expand Down Expand Up @@ -48,18 +49,25 @@ export const ResetPassword = () => {
});

return (
<Card>
<form onSubmit={form.onSubmit(handleSubmit)}>
<PasswordInput {...form.getInputProps('password')} label={t`New Password`} required/>
<PasswordInput {...form.getInputProps('password_confirmation')} label={t`Confirm Password`} required/>
<Button type="submit" fullWidth disabled={mutate.isLoading}>
{mutate.isLoading ? t`Working...` : t`Reset password`}
</Button>
</form>
<footer>
<NavLink to={'/auth/login'}>{t`Back to login`}</NavLink>
</footer>
</Card>
<>
<header className={classes.header}>
<h2>{t`Reset Password`}</h2>
<p>{t`Please enter your new password`}</p>
</header>
<Card>
<form onSubmit={form.onSubmit(handleSubmit)}>
<PasswordInput {...form.getInputProps('password')} label={t`New Password`} required/>
<PasswordInput {...form.getInputProps('password_confirmation')} label={t`Confirm Password`} required/>
<Button type="submit" fullWidth disabled={mutate.isLoading}>
{mutate.isLoading ? t`Working...` : t`Reset password`}
</Button>
</form>
<footer>
<NavLink to={'/auth/login'}>{t`Back to login`}</NavLink>
</footer>
</Card>
</>

)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ export const ManageProfile = () => {
userData: formValues,
}, {
onSuccess: () => {
form.reset();
showSuccess(t`Profile updated successfully`);
},
onError: (error: any) => {
showError(t`Something went wrong. Please try again.`);
errorHandler(form, error);
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,12 @@ const SelectTickets = (props: SelectTicketsProps) => {
}
}

const isButtonDisabled = ticketMutation.isLoading
|| !ticketAreAvailable
|| selectedTicketQuantitySum === 0
|| props.widgetMode === 'preview'
|| tickets?.every(ticket => ticket.is_sold_out);

return (
<div className={'hi-ticket-widget-container'}
ref={resizeRef}
Expand Down Expand Up @@ -326,7 +332,7 @@ const SelectTickets = (props: SelectTicketsProps) => {
__html: event.settings.ticket_page_message.replace(/\n/g, '<br/>')
}} className={'hi-ticket-page-message'}/>
)}
<Button disabled={props.widgetMode === 'preview'} fullWidth className={'hi-continue-button'}
<Button disabled={isButtonDisabled} fullWidth className={'hi-continue-button'}
type={"submit"}
loading={ticketMutation.isLoading}>
{props.continueButtonText || event?.settings?.continue_button_text || t`Continue`}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/locales/de.js

Large diffs are not rendered by default.

Loading

0 comments on commit 96f5fac

Please sign in to comment.