feat: vylepšení Pizza day
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
This commit is contained in:
@@ -175,6 +175,11 @@ function App() {
|
||||
}
|
||||
}, [auth?.login, data?.pizzaDay?.orders])
|
||||
|
||||
// Kontrola, zda má uživatel vybranou volbu PIZZA
|
||||
const userHasPizzaChoice = useMemo(() => {
|
||||
return auth?.login ? data?.choices?.PIZZA?.[auth.login] != null : false;
|
||||
}, [data?.choices?.PIZZA, auth?.login]);
|
||||
|
||||
useEffect(() => {
|
||||
if (choiceRef?.current?.value && choiceRef.current.value !== "") {
|
||||
const locationKey = choiceRef.current.value as LunchChoice;
|
||||
@@ -226,10 +231,65 @@ function App() {
|
||||
}
|
||||
}, [auth?.login, easterEgg?.duration, easterEgg?.url, eggImage]);
|
||||
|
||||
// Pomocná funkce pro kontrolu a potvrzení změny volby při existujícím Pizza day
|
||||
const checkPizzaDayBeforeChange = async (newLocationKey: LunchChoice): Promise<boolean> => {
|
||||
if (!auth?.login || !data) return false;
|
||||
|
||||
// Kontrola, zda uživatel má vybranou PIZZA a mění na něco jiného
|
||||
const hasPizzaChoice = data.choices?.PIZZA?.[auth.login] != null;
|
||||
const isCreator = data.pizzaDay?.creator === auth.login;
|
||||
const isPizzaDayCreated = data.pizzaDay?.state === PizzaDayState.CREATED;
|
||||
|
||||
// Pokud není vybraná PIZZA nebo přepínáme na PIZZA, není potřeba kontrolovat
|
||||
if (!hasPizzaChoice || newLocationKey === LunchChoice.PIZZA) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pokud uživatel není zakladatel Pizza day, není potřeba dialogu
|
||||
if (!isCreator || !data?.pizzaDay) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Uživatel je zakladatel Pizza day a mění volbu z PIZZA
|
||||
if (!isPizzaDayCreated) {
|
||||
// Pizza day není ve stavu CREATED, nelze změnit volbu
|
||||
alert(`Nelze změnit volbu. Pizza day je ve stavu "${data.pizzaDay.state}" a musí být nejprve dokončen.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pizza day je CREATED, zobrazit potvrzovací dialog
|
||||
const confirmed = window.confirm(
|
||||
'Jsi zakladatel aktivního Pizza day. Změna volby smaže celý Pizza day včetně všech objednávek. Pokračovat?'
|
||||
);
|
||||
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Uživatel potvrdil, smazat Pizza day
|
||||
try {
|
||||
await deletePizzaDay();
|
||||
return true;
|
||||
} catch (error: any) {
|
||||
alert(`Chyba při mazání Pizza day: ${error.message || error}`);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const doAddClickFoodChoice = async (location: LunchChoice, foodIndex?: number) => {
|
||||
if (document.getSelection()?.type !== 'Range') { // pouze pokud se nejedná o výběr textu
|
||||
if (canChangeChoice && auth?.login) {
|
||||
await addChoice({ body: { locationKey: location, foodIndex, dayIndex } });
|
||||
// Kontrola Pizza day před změnou volby
|
||||
const canProceed = await checkPizzaDayBeforeChange(location);
|
||||
if (!canProceed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await addChoice({ body: { locationKey: location, foodIndex, dayIndex } });
|
||||
} catch (error: any) {
|
||||
alert(`Chyba při změně volby: ${error.message || error}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,11 +297,32 @@ function App() {
|
||||
const doAddChoice = async (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const locationKey = event.target.value as LunchChoice;
|
||||
if (canChangeChoice && auth?.login) {
|
||||
await addChoice({ body: { locationKey, dayIndex } });
|
||||
if (foodChoiceRef.current?.value) {
|
||||
foodChoiceRef.current.value = "";
|
||||
// Kontrola Pizza day před změnou volby
|
||||
const canProceed = await checkPizzaDayBeforeChange(locationKey);
|
||||
if (!canProceed) {
|
||||
// Uživatel zrušil akci nebo došlo k chybě, reset výběru zpět na PIZZA
|
||||
if (choiceRef.current) {
|
||||
choiceRef.current.value = LunchChoice.PIZZA;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await addChoice({ body: { locationKey, dayIndex } });
|
||||
if (foodChoiceRef.current?.value) {
|
||||
foodChoiceRef.current.value = "";
|
||||
}
|
||||
choiceRef.current?.blur();
|
||||
} catch (error: any) {
|
||||
alert(`Chyba při změně volby: ${error.message || error}`);
|
||||
// Reset výběru zpět
|
||||
const hasPizzaChoice = data?.choices?.PIZZA?.[auth.login] != null;
|
||||
if (choiceRef.current && hasPizzaChoice) {
|
||||
choiceRef.current.value = LunchChoice.PIZZA;
|
||||
} else if (choiceRef.current) {
|
||||
choiceRef.current.value = "";
|
||||
}
|
||||
}
|
||||
choiceRef.current?.blur();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,28 +637,28 @@ function App() {
|
||||
<div className="user-actions">
|
||||
{login === auth.login && canChangeChoice && locationKey === LunchChoice.OBJEDNAVAM && <span title='Označit/odznačit se jako objednávající'>
|
||||
<FontAwesomeIcon onClick={() => {
|
||||
markAsBuyer();
|
||||
}} icon={faBasketShopping} className={isBuyer ? 'buyer-icon' : 'action-icon'} style={{cursor: 'pointer'}} />
|
||||
markAsBuyer();
|
||||
}} icon={faBasketShopping} className={isBuyer ? 'buyer-icon' : 'action-icon'} style={{ cursor: 'pointer' }} />
|
||||
</span>}
|
||||
{login !== auth.login && locationKey === LunchChoice.OBJEDNAVAM && isBuyer && <span title='Objednávající'>
|
||||
<FontAwesomeIcon onClick={() => {
|
||||
copyNote(userPayload.note!);
|
||||
}} icon={faBasketShopping} className='buyer-icon' />
|
||||
copyNote(userPayload.note!);
|
||||
}} icon={faBasketShopping} className='buyer-icon' />
|
||||
</span>}
|
||||
{login !== auth.login && canChangeChoice && userPayload?.note?.length && <span title='Převzít poznámku'>
|
||||
<FontAwesomeIcon onClick={() => {
|
||||
copyNote(userPayload.note!);
|
||||
}} className='action-icon' icon={faComment} />
|
||||
copyNote(userPayload.note!);
|
||||
}} className='action-icon' icon={faComment} />
|
||||
</span>}
|
||||
{login === auth.login && canChangeChoice && <span title='Upravit poznámku'>
|
||||
<FontAwesomeIcon onClick={() => {
|
||||
setNoteModalOpen(true);
|
||||
}} className='action-icon' icon={faNoteSticky} />
|
||||
setNoteModalOpen(true);
|
||||
}} className='action-icon' icon={faNoteSticky} />
|
||||
</span>}
|
||||
{login === auth.login && canChangeChoice && <span title={`Odstranit volbu ${locationName}, včetně případných zvolených jídel`}>
|
||||
<FontAwesomeIcon onClick={() => {
|
||||
doRemoveChoices(key as LunchChoice);
|
||||
}} className='action-icon' icon={faTrashCan} />
|
||||
doRemoveChoices(key as LunchChoice);
|
||||
}} className='action-icon' icon={faTrashCan} />
|
||||
</span>}
|
||||
</div>
|
||||
</div>
|
||||
@@ -589,11 +670,11 @@ function App() {
|
||||
return <div key={foodIndex} className="food-choice-item">
|
||||
<span className="food-choice-name">{foodName}</span>
|
||||
{login === auth.login && canChangeChoice &&
|
||||
<span title={`Odstranit ${foodName}`}>
|
||||
<FontAwesomeIcon onClick={() => {
|
||||
doRemoveFoodChoice(restaurantKey, foodIndex);
|
||||
}} className='action-icon' icon={faTrashCan} />
|
||||
</span>}
|
||||
<span title={`Odstranit ${foodName}`}>
|
||||
<FontAwesomeIcon onClick={() => {
|
||||
doRemoveFoodChoice(restaurantKey, foodIndex);
|
||||
}} className='action-icon' icon={faTrashCan} />
|
||||
</span>}
|
||||
</div>
|
||||
})}
|
||||
</div>
|
||||
@@ -613,7 +694,7 @@ function App() {
|
||||
: <div className='no-votes mt-4'>Zatím nikdo nehlasoval...</div>
|
||||
}
|
||||
</div>
|
||||
{dayIndex === data.todayDayIndex &&
|
||||
{dayIndex === data.todayDayIndex && userHasPizzaChoice &&
|
||||
<div className='pizza-section fade-in'>
|
||||
{!data.pizzaDay &&
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user