Skip to content

Commit

Permalink
feat: Add options to customize cocktail step actions in the settings (#…
Browse files Browse the repository at this point in the history
…171)

Signed-off-by: Johannes Groß <mail@gross-johannes.de>
  • Loading branch information
jo-gross authored Feb 28, 2024
1 parent 4c82527 commit 5c91163
Show file tree
Hide file tree
Showing 16 changed files with 694 additions and 94 deletions.
20 changes: 3 additions & 17 deletions components/cocktails/CocktailRecipeForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { TagsInput } from 'react-tag-input-component';
import { Field, FieldArray, Formik, FormikProps } from 'formik';
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import { Garnish, Glass, Ingredient, WorkspaceCocktailRecipeStepAction, WorkspaceSetting } from '@prisma/client';
import { Garnish, Glass, Ingredient, WorkspaceCocktailRecipeStepAction } from '@prisma/client';
import { updateTags, validateTag } from '../../models/tags/TagUtils';
import { UploadDropZone } from '../UploadDropZone';
import { convertToBase64 } from '../../lib/Base64Converter';
Expand All @@ -24,7 +24,6 @@ import { IngredientForm } from '../ingredients/IngredientForm';
import { GlassForm } from '../glasses/GlassForm';
import { CocktailRecipeFullWithImage } from '../../models/CocktailRecipeFullWithImage';
import { UserContext } from '../../lib/context/UserContextProvider';
import { WorkspaceSettingKey } from '.prisma/client';
import DeepDiff from 'deep-diff';
import { GlassModel } from '../../models/GlassModel';

Expand Down Expand Up @@ -785,25 +784,12 @@ export function CocktailRecipeForm(props: CocktailRecipeFormProps) {
<option disabled={true}>Lade...</option>
) : (
Object.entries(_.groupBy(actions, 'actionGroup')).map(([group, groupActions]) => (
<optgroup
key={`form-recipe-step-${step.id}-action-group-${group}`}
label={
JSON.parse(
(userContext.workspace?.WorkspaceSetting as WorkspaceSetting[]).find(
(setting) => setting.setting == WorkspaceSettingKey.translations,
)?.value ?? '{}',
)['de'][group] ?? group
}
>
<optgroup key={`form-recipe-step-${step.id}-action-group-${group}`} label={userContext.getTranslation(group, 'de')}>
{groupActions
.sort((a, b) => a.name.localeCompare(b.name))
.map((action) => (
<option key={`form-recipe-step-${step.id}-action-${action.id}`} value={action.id}>
{JSON.parse(
(userContext.workspace?.WorkspaceSetting as WorkspaceSetting[]).find(
(setting) => setting.setting == WorkspaceSettingKey.translations,
)?.value ?? '{}',
)['de'][action.name] ?? action.name}
{userContext.getTranslation(action.name, 'de')}
</option>
))}
)
Expand Down
9 changes: 1 addition & 8 deletions components/cocktails/CompactCocktailRecipeInstruction.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { CocktailRecipeFull } from '../../models/CocktailRecipeFull';
import React, { useContext } from 'react';
import DefaultGlassIcon from '../DefaultGlassIcon';
import { WorkspaceSettingKey } from '.prisma/client';
import { UserContext } from '../../lib/context/UserContextProvider';
import { WorkspaceSetting } from '@prisma/client';
import Image from 'next/image';

interface CompactCocktailRecipeInstructionProps {
Expand Down Expand Up @@ -54,12 +52,7 @@ export function CompactCocktailRecipeInstruction(props: CompactCocktailRecipeIns
?.sort((a, b) => a.stepNumber - b.stepNumber)
?.map((step, index) => (
<div key={`step-${step.id}`} className={'break-words pb-2'}>
<span className={'font-bold'}>
{JSON.parse(
(userContext.workspace?.WorkspaceSetting as WorkspaceSetting[]).find((setting) => setting.setting == WorkspaceSettingKey.translations)
?.value ?? '{}',
)['de'][step.action?.name] ?? step.action?.name}
</span>
<span className={'font-bold'}>{userContext.getTranslation(step.action.name, 'de')}</span>
{step.ingredients
?.sort((a, b) => a.ingredientNumber - b.ingredientNumber)
.map((ingredient, indexIngredient) => (
Expand Down
23 changes: 22 additions & 1 deletion components/layout/AuthBoundary/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React, { useCallback, useEffect, useState } from 'react';
import { signOut, useSession } from 'next-auth/react';
import { Role, User, UserSetting, WorkspaceUser } from '@prisma/client';
import { Role, User, UserSetting, WorkspaceSetting, WorkspaceUser } from '@prisma/client';
import { PageCenter } from '../PageCenter';
import { Loading } from '../../Loading';
import { UserContext } from '../../../lib/context/UserContextProvider';
import { alertService } from '../../../lib/alertService';
import { useRouter } from 'next/router';
import { WorkspaceFull } from '../../../models/WorkspaceFull';
import { WorkspaceSettingKey } from '.prisma/client';

interface AlertBoundaryProps {
children: React.ReactNode;
Expand Down Expand Up @@ -85,6 +86,24 @@ export function AuthBoundary(props: AlertBoundaryProps) {
fetchWorkspace();
}, [fetchWorkspace]);

const getTranslationOrNull = useCallback(
(key: string, language: 'de') => {
return (
JSON.parse((workspace?.WorkspaceSetting as WorkspaceSetting[]).find((setting) => setting.setting == WorkspaceSettingKey.translations)?.value ?? '{}')[
language
][key] ?? null
);
},
[workspace],
);

const getTranslation = useCallback(
(key: string, language: 'de') => {
return getTranslationOrNull(key, language) ?? key;
},
[getTranslationOrNull],
);

return (
<>
<UserContext.Provider
Expand Down Expand Up @@ -141,6 +160,8 @@ export function AuthBoundary(props: AlertBoundaryProps) {
alertService.error('Es ist ein Fehler aufgetreten');
});
},
getTranslation: getTranslation,
getTranslationOrNull: getTranslationOrNull,
}}
>
{userLoading ? (
Expand Down
10 changes: 2 additions & 8 deletions components/modals/CocktailDetailModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import { UserContext } from '../../lib/context/UserContextProvider';
import DefaultGlassIcon from '../DefaultGlassIcon';
import { Role, WorkspaceSetting } from '@prisma/client';
import { WorkspaceSettingKey } from '.prisma/client';
import { Role } from '@prisma/client';
import { alertService } from '../../lib/alertService';
import Image from 'next/image';
import AvatarImage from '../AvatarImage';
Expand Down Expand Up @@ -157,12 +156,7 @@ export function CocktailDetailModal(props: CocktailDetailModalProps) {
<div className={'grid grid-cols-2 gap-4'}>
{loadedCocktail.steps.map((step) => (
<div key={'cocktail-details-step-' + step.id} className={'col-span-2 space-y-2 rounded-lg border-2 border-base-300 p-2'}>
<span className={'text-xl font-bold'}>
{JSON.parse(
(userContext.workspace?.WorkspaceSetting as WorkspaceSetting[]).find((setting) => setting.setting == WorkspaceSettingKey.translations)
?.value ?? '{}',
)['de'][step.action?.name] ?? step.action?.name}
</span>
<span className={'text-xl font-bold'}>{userContext.getTranslation(step.action.name, 'de')}</span>
{step.ingredients.map((ingredient) => (
<div key={'cocktail-details-step-ingredient-' + ingredient.id} className={'pl-2'}>
<div className={'flex-1'}>
Expand Down
112 changes: 112 additions & 0 deletions components/modals/CocktailStepActionGroupModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { Formik } from 'formik';
import React, { useContext } from 'react';
import { UserContext } from '../../lib/context/UserContextProvider';
import { ModalContext } from '../../lib/context/ModalContextProvider';
import { alertService } from '../../lib/alertService';
import { useRouter } from 'next/router';

interface CocktailStepActionGroupModalProps {
actionGroup: string;
}

export default function CocktailStepActionGroupModal(props: CocktailStepActionGroupModalProps) {
const userContext = useContext(UserContext);
const modalContext = useContext(ModalContext);

const router = useRouter();

const { workspaceId } = router.query;

return (
<div className={'flex flex-col gap-2'}>
<div className={'text-2xl font-bold'}>Zubereitungsgruppe Anpassen</div>
<Formik
initialValues={{
lableDE: userContext.getTranslationOrNull(props.actionGroup, 'de') ?? '',
}}
onSubmit={async (values) => {
try {
const body = {
actionGroup: props.actionGroup,
translations: {
de: values.lableDE,
},
};
const response = await fetch(`/api/workspaces/${workspaceId}/actions/group`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (response.status.toString().startsWith('2')) {
router.reload();
modalContext.closeModal();
alertService.success('Zubereitungsgruppe erfolgreich gespeichert');
} else {
const body = await response.json();
console.error('CocktailStepActionGroupModal -> onSubmit[update]', response);
alertService.error(body.message ?? 'Fehler beim Speichern der Zubereitungsgruppe', response.status, response.statusText);
}
} catch (error) {
console.error('CocktailStepActionGroupModal -> onSubmit', error);
alertService.error('Es ist ein Fehler aufgetreten');
}
}}
validate={(values) => {
const errors: { [key: string]: string } = {};

if (!values.lableDE || values.lableDE.trim() == '') {
errors.lableDE = 'Ungültiger Bezeichner';
}

return errors;
}}
>
{({ values, handleChange, handleSubmit, isSubmitting, errors, touched, setFieldValue }) => (
<form onSubmit={handleSubmit} className={'flex flex-col gap-2'}>
<div className={'grid grid-cols-2 gap-2'}>
<div className={'form-control'}>
<label className={'label'}>
<div className={'label-text'}>Identifier</div>
<div className={'label-text-alt text-error'}></div>
</label>
<input
id={'actionGroup'}
readOnly={true}
name={'actionGroup'}
value={props.actionGroup}
onChange={handleChange}
className={`input input-bordered input-disabled`}
/>
</div>
<div className={'form-control'}>
<label className={'label'}>
<div className={'label-text'}>Deutsch</div>
<div className={'label-text-alt text-error'}>
<span>{errors.lableDE && touched.lableDE ? errors.lableDE : ''}</span>
<span>*</span>
</div>
</label>
<input id={'lableDE'} name={'lableDE'} value={values.lableDE} onChange={handleChange} className={'input input-bordered'} />
</div>
</div>
<div className={'flex justify-end gap-2'}>
<button
className={'btn btn-outline btn-error'}
type={'button'}
onClick={() => {
modalContext.closeModal();
}}
>
Abbrechen
</button>
<button className={'btn btn-primary'} type={'submit'}>
{isSubmitting ? <span className={'spinner loading-spinner'} /> : <></>}
Speichern
</button>
</div>
</form>
)}
</Formik>
</div>
);
}
Loading

0 comments on commit 5c91163

Please sign in to comment.