Merge pull request 'tasting-notes' (#50) from tasting-notes into staging
Reviewed-on: #50
This commit is contained in:
commit
d7e008f308
src
routes
types
utils/validation
@ -1,9 +1,9 @@
|
||||
import express, { Request, Response } from 'express'
|
||||
import { collections } from '../services/database.service'
|
||||
import { Review } from '../models'
|
||||
import { Coffee, Review, Sake, Spirit, Wine } from '../models'
|
||||
import { reviewValidation, handleReqError, handleReqSuccess } from '../utils'
|
||||
import Joi from 'joi'
|
||||
import { DBcollection } from '../types'
|
||||
import { DBcollection, TastingNoteKey } from '../types'
|
||||
import { BSON } from 'mongodb'
|
||||
|
||||
export const reviewsRouter = express.Router()
|
||||
@ -49,36 +49,46 @@ reviewsRouter.post('/', async (req: Request, res: Response) => {
|
||||
const { productId } = review
|
||||
const _id = new BSON.ObjectId(productId)
|
||||
|
||||
const existingWine = await collections[DBcollection.Wines]?.findOne({
|
||||
let product: Wine | Spirit | Sake | null | undefined = await collections[
|
||||
DBcollection.Wines
|
||||
]?.findOne<Wine>({
|
||||
_id
|
||||
})
|
||||
|
||||
if (!existingWine) {
|
||||
const existingSake = await collections[DBcollection.Sake]?.findOne({
|
||||
if (!product) {
|
||||
product = await collections[DBcollection.Sake]?.findOne<Sake>({
|
||||
_id
|
||||
})
|
||||
|
||||
if (!existingSake) {
|
||||
const existingSpirit = await collections[DBcollection.Spirits]?.findOne(
|
||||
{
|
||||
_id
|
||||
}
|
||||
)
|
||||
if (!product) {
|
||||
product = await collections[DBcollection.Spirits]?.findOne<Spirit>({
|
||||
_id
|
||||
})
|
||||
|
||||
if (!existingSpirit) {
|
||||
const existingCoffee = await collections[
|
||||
if (!product) {
|
||||
const coffee = await collections[
|
||||
DBcollection.Coffee
|
||||
]?.findOne({
|
||||
]?.findOne<Coffee>({
|
||||
_id
|
||||
})
|
||||
|
||||
if (!existingCoffee) {
|
||||
if (!coffee) {
|
||||
throw new Error('product with provided "productId" does not exists')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add age property to tasting note, if product has vintage property
|
||||
if (product) {
|
||||
const { vintage } = product
|
||||
|
||||
if (typeof vintage === 'number') {
|
||||
review.tastingNote[TastingNoteKey.TextureAndBalance].age =
|
||||
new Date().getFullYear() - vintage
|
||||
}
|
||||
}
|
||||
|
||||
const result = await collections[DBcollection.Reviews]?.insertOne(review)
|
||||
|
||||
handleReqSuccess(res, result, 'review')
|
||||
|
@ -38,16 +38,15 @@ import {
|
||||
TextureAndBalanceKey,
|
||||
Sweetness,
|
||||
Concentration,
|
||||
TanninType,
|
||||
RipeTannin,
|
||||
UnripeTannin,
|
||||
Body,
|
||||
FlavourIntensity,
|
||||
PalateLength,
|
||||
ReasoningConcentration,
|
||||
Quality,
|
||||
ReadinessToDrink,
|
||||
ReasoningKey
|
||||
ReasoningKey,
|
||||
TanninString,
|
||||
TanninObject
|
||||
} from './review/'
|
||||
|
||||
export enum RatingOption {
|
||||
@ -106,9 +105,7 @@ export interface TastingNote {
|
||||
[TastingNoteKey.TextureAndBalance]: {
|
||||
[TextureAndBalanceKey.Sweetness]: Sweetness
|
||||
[TextureAndBalanceKey.Acidity]: Concentration
|
||||
[TextureAndBalanceKey.Tannin]: {
|
||||
[key in Concentration]: { [key in TanninType]: RipeTannin | UnripeTannin }
|
||||
}
|
||||
[TextureAndBalanceKey.Tannin]: TanninString | TanninObject
|
||||
[TextureAndBalanceKey.Alcohol]: Concentration
|
||||
[TextureAndBalanceKey.Body]: Body
|
||||
[TextureAndBalanceKey.FlavourIntensity]: FlavourIntensity
|
||||
|
@ -4,7 +4,7 @@ export enum WhiteColour {
|
||||
LemonGreen = 'Lemon-Green',
|
||||
Lemon = 'Lemon',
|
||||
Gold = 'Gold',
|
||||
WhiteBrown = 'White-Brown' // FIXME: duplicate
|
||||
WhiteBrown = 'White-Brown'
|
||||
}
|
||||
|
||||
// Skin Contact (wine, spirits)
|
||||
@ -17,7 +17,7 @@ export enum AmberColour {
|
||||
export enum RoseColour {
|
||||
Pink = 'Pink',
|
||||
Salmon = 'Salmon',
|
||||
RoseOrange = 'Rose-Orange', // FIXME: duplicate
|
||||
RoseOrange = 'Rose-Orange',
|
||||
OnionSkin = 'Onion-Skin'
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,12 @@ export enum PrimaryFlavoursAndAromasKey {
|
||||
Faults = 'faults'
|
||||
}
|
||||
|
||||
export enum RequiredPrimaryFlavoursAndAromasKey {
|
||||
Condition = PrimaryFlavoursAndAromasKey.Condition,
|
||||
Intensity = PrimaryFlavoursAndAromasKey.Intensity,
|
||||
Age = PrimaryFlavoursAndAromasKey.Age
|
||||
}
|
||||
|
||||
export enum Condition {
|
||||
Clean = 'Clean',
|
||||
Unclean = 'Unclean'
|
||||
|
@ -26,6 +26,22 @@ export enum Concentration {
|
||||
High = 'High'
|
||||
}
|
||||
|
||||
export enum TanninString {
|
||||
Low = 'Low'
|
||||
}
|
||||
|
||||
export interface TanninObject {
|
||||
[Concentration.Low]: {
|
||||
[key in TanninType]: RipeTannin | UnripeTannin
|
||||
}
|
||||
[Concentration.Medium]: {
|
||||
[key in TanninType]: RipeTannin | UnripeTannin
|
||||
}
|
||||
[Concentration.High]: {
|
||||
[key in TanninType]: RipeTannin | UnripeTannin
|
||||
}
|
||||
}
|
||||
|
||||
export enum TanninType {
|
||||
Ripe = 'Ripe',
|
||||
Unripe = 'Unripe'
|
||||
|
@ -55,10 +55,13 @@ import {
|
||||
ReasoningKey,
|
||||
ReasoningConcentration,
|
||||
Quality,
|
||||
ReadinessToDrink
|
||||
ReadinessToDrink,
|
||||
RequiredPrimaryFlavoursAndAromasKey,
|
||||
TanninString,
|
||||
TanninObject
|
||||
} from '../../types'
|
||||
import { compareArrays, isObject } from '../utils'
|
||||
import { producerIdValidation } from './'
|
||||
import { producerIdValidation, validateStringValue } from './'
|
||||
|
||||
export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
Joi.object({
|
||||
@ -103,10 +106,23 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
|
||||
if (!compareArrays(visualAssessmentKeys, validVisualAssessmentKeys)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. "visualAssessment-visualAssessment" object has to include the following keys: [${validVisualAssessmentKeys.join(', ')}]`
|
||||
`provided "tastingNote" is not valid. "visualAssessment" object has to include the following keys: [${validVisualAssessmentKeys.join(', ')}]`
|
||||
)
|
||||
}
|
||||
|
||||
const messageWithValidOptions = (
|
||||
noteKey: TastingNoteKey,
|
||||
noteSubKey:
|
||||
| VisualAssessmentKey
|
||||
| PrimaryFlavoursAndAromasKey
|
||||
| TextureAndBalanceKey,
|
||||
options: object,
|
||||
product?: string
|
||||
) =>
|
||||
message(
|
||||
`provided "tastingNote" is not valid. Valid options for "${[noteKey, noteSubKey].join('-')}"${product ? ` for "${product}"` : ''} are: [${Object.values(options).join(', ')}]`
|
||||
)
|
||||
|
||||
/**
|
||||
* visualAssessment-clarity validation
|
||||
*/
|
||||
@ -115,12 +131,11 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
VisualAssessmentKey.Clarity
|
||||
]
|
||||
|
||||
if (
|
||||
typeof clarity !== 'string' ||
|
||||
!(clarity in ClarityVisualAssessment)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-clarity" are: [${Object.values(ClarityVisualAssessment).join(', ')}]`
|
||||
if (validateStringValue(clarity, ClarityVisualAssessment)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.VisualAssessment,
|
||||
VisualAssessmentKey.Clarity,
|
||||
ClarityVisualAssessment
|
||||
)
|
||||
}
|
||||
|
||||
@ -132,9 +147,11 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
VisualAssessmentKey.Nature
|
||||
]
|
||||
|
||||
if (typeof nature !== 'string' || !(nature in NatureVisualAssessment)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-nature" are: [${Object.values(NatureVisualAssessment).join(', ')}]`
|
||||
if (validateStringValue(nature, NatureVisualAssessment)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.VisualAssessment,
|
||||
VisualAssessmentKey.Nature,
|
||||
NatureVisualAssessment
|
||||
)
|
||||
}
|
||||
|
||||
@ -145,33 +162,20 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.VisualAssessment][
|
||||
VisualAssessmentKey.Colour
|
||||
]
|
||||
const validWhiteColourOptions: WhiteColour[] =
|
||||
Object.values(WhiteColour)
|
||||
const validAmberColourOptions: AmberColour[] =
|
||||
Object.values(AmberColour)
|
||||
const validRoseColourOptions = Object.values(RoseColour)
|
||||
const validRedColourOptions = Object.values(RedColour)
|
||||
const validBlueColourOptions = Object.values(BlueColour)
|
||||
const validGreenColourOptions = Object.values(GreenColour)
|
||||
const validColorOptions = {
|
||||
...WhiteColour,
|
||||
...AmberColour,
|
||||
...RoseColour,
|
||||
...RedColour,
|
||||
...BlueColour,
|
||||
...GreenColour
|
||||
}
|
||||
|
||||
if (
|
||||
typeof colour !== 'string' ||
|
||||
(!validWhiteColourOptions.includes(colour as WhiteColour) &&
|
||||
!validAmberColourOptions.includes(colour as AmberColour) &&
|
||||
!validRoseColourOptions.includes(colour as RoseColour) &&
|
||||
!validRedColourOptions.includes(colour as RedColour) &&
|
||||
!validBlueColourOptions.includes(colour as BlueColour) &&
|
||||
!validGreenColourOptions.includes(colour as GreenColour))
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-colour" are: [${[
|
||||
...validWhiteColourOptions,
|
||||
...validAmberColourOptions,
|
||||
...validRoseColourOptions,
|
||||
...validRedColourOptions,
|
||||
...validBlueColourOptions,
|
||||
...validGreenColourOptions
|
||||
].join(', ')}]`
|
||||
if (validateStringValue(colour, validColorOptions)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.VisualAssessment,
|
||||
VisualAssessmentKey.Colour,
|
||||
validColorOptions
|
||||
)
|
||||
}
|
||||
|
||||
@ -181,11 +185,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
switch (productType) {
|
||||
case ProductType.Wine:
|
||||
{
|
||||
const validWineColours = Object.values(WineColour)
|
||||
|
||||
if (!(validWineColours as string[]).includes(colour)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-colour" for ${productType} are: [${validWineColours.join(', ')}]`
|
||||
if (validateStringValue(colour, WineColour)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.VisualAssessment,
|
||||
VisualAssessmentKey.Colour,
|
||||
WineColour,
|
||||
productType
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -194,11 +199,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
|
||||
case ProductType.Sake:
|
||||
{
|
||||
const validSakeColours = Object.values(SakeColour)
|
||||
|
||||
if (!(validSakeColours as string[]).includes(colour)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-colour" for ${productType} are: [${validSakeColours.join(', ')}]`
|
||||
if (validateStringValue(colour, SakeColour)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.VisualAssessment,
|
||||
VisualAssessmentKey.Colour,
|
||||
SakeColour,
|
||||
productType
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -207,11 +213,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
|
||||
case ProductType.Spirit:
|
||||
{
|
||||
const validSpiritColours = Object.values(SpiritColour)
|
||||
|
||||
if (!(validSpiritColours as string[]).includes(colour)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-colour" for ${productType} are: [${validSpiritColours.join(', ')}]`
|
||||
if (validateStringValue(colour, SpiritColour)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.VisualAssessment,
|
||||
VisualAssessmentKey.Colour,
|
||||
SpiritColour,
|
||||
productType
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -231,16 +238,28 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
const validPrimaryFlavoursAndAromasKeys = Object.values(
|
||||
PrimaryFlavoursAndAromasKey
|
||||
)
|
||||
const requiredPrimaryFlavoursAndAromasKeys = Object.values(
|
||||
RequiredPrimaryFlavoursAndAromasKey
|
||||
)
|
||||
|
||||
if (
|
||||
!compareArrays(
|
||||
primaryFlavoursAndAromasKeys,
|
||||
validPrimaryFlavoursAndAromasKeys
|
||||
)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. "visualAssessment-primaryFlavoursAndAromas" object has to include the following keys: [${validPrimaryFlavoursAndAromasKeys.join(', ')}]`
|
||||
)
|
||||
for (const requiredKey of requiredPrimaryFlavoursAndAromasKeys) {
|
||||
if (!primaryFlavoursAndAromasKeys.includes(requiredKey)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. "visualAssessment-primaryFlavoursAndAromas" object has to include the following keys: [${requiredPrimaryFlavoursAndAromasKeys.join(', ')}]`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for (const key of primaryFlavoursAndAromasKeys) {
|
||||
if (
|
||||
!validPrimaryFlavoursAndAromasKeys.includes(
|
||||
key as PrimaryFlavoursAndAromasKey
|
||||
)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. "${key}" is not a valid key for "visualAssessment-primaryFlavoursAndAromas" object, valid keys are: [${validPrimaryFlavoursAndAromasKeys.join(', ')}]`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// primaryFlavoursAndAromas-condition validation
|
||||
@ -248,14 +267,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Condition
|
||||
]
|
||||
const validConditionOptions: Condition[] = Object.values(Condition)
|
||||
|
||||
if (
|
||||
typeof condition !== 'string' ||
|
||||
!validConditionOptions.includes(condition)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-condition" are: [${validConditionOptions.join(', ')}]`
|
||||
if (validateStringValue(condition, Condition)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Condition,
|
||||
Condition
|
||||
)
|
||||
}
|
||||
|
||||
@ -264,14 +281,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Intensity
|
||||
]
|
||||
const validIntensityOptions: Intensity[] = Object.values(Intensity)
|
||||
|
||||
if (
|
||||
typeof intensity !== 'string' ||
|
||||
!validIntensityOptions.includes(intensity)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-intensity" are: [${validIntensityOptions.join(', ')}]`
|
||||
if (validateStringValue(intensity, Intensity)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Intensity,
|
||||
Intensity
|
||||
)
|
||||
}
|
||||
|
||||
@ -280,11 +295,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Age
|
||||
]
|
||||
const validAgeOptions: Age[] = Object.values(Age)
|
||||
|
||||
if (typeof age !== 'string' || !validAgeOptions.includes(age)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-age" are: [${validAgeOptions.join(', ')}]`
|
||||
if (validateStringValue(age, Age)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Age,
|
||||
Age
|
||||
)
|
||||
}
|
||||
|
||||
@ -293,29 +309,22 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Fruit
|
||||
]
|
||||
const validFruitOptions: (
|
||||
| CitrusFruit
|
||||
| AppleFruit
|
||||
| StoneFruit
|
||||
| RedFruit
|
||||
| BlackFruit
|
||||
| ChocolateFruit
|
||||
| TropicalFruit
|
||||
| MelonFruit
|
||||
)[] = [
|
||||
...Object.values(CitrusFruit),
|
||||
...Object.values(AppleFruit),
|
||||
...Object.values(StoneFruit),
|
||||
...Object.values(RedFruit),
|
||||
...Object.values(BlackFruit),
|
||||
...Object.values(ChocolateFruit),
|
||||
...Object.values(TropicalFruit),
|
||||
...Object.values(MelonFruit)
|
||||
]
|
||||
const validFruitOptions = {
|
||||
...CitrusFruit,
|
||||
...AppleFruit,
|
||||
...StoneFruit,
|
||||
...RedFruit,
|
||||
...BlackFruit,
|
||||
...ChocolateFruit,
|
||||
...TropicalFruit,
|
||||
...MelonFruit
|
||||
}
|
||||
|
||||
if (typeof fruit !== 'string' || !validFruitOptions.includes(fruit)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-fruit" are: [${validFruitOptions.join(', ')}]`
|
||||
if (fruit && validateStringValue(fruit, validFruitOptions)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Fruit,
|
||||
validFruitOptions
|
||||
)
|
||||
}
|
||||
|
||||
@ -324,14 +333,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Floral
|
||||
]
|
||||
const validFloralOptions: Floral[] = Object.values(Floral)
|
||||
|
||||
if (
|
||||
typeof floral !== 'string' ||
|
||||
!validFloralOptions.includes(floral)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-floral" are: [${validFloralOptions.join(', ')}]`
|
||||
if (floral && validateStringValue(floral, Floral)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Floral,
|
||||
Floral
|
||||
)
|
||||
}
|
||||
|
||||
@ -340,14 +347,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Vegetal
|
||||
]
|
||||
const validVegetalOptions: Vegetal[] = Object.values(Vegetal)
|
||||
|
||||
if (
|
||||
typeof vegetal !== 'string' ||
|
||||
!validVegetalOptions.includes(vegetal)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-vegetal" are: [${validVegetalOptions.join(', ')}]`
|
||||
if (vegetal && validateStringValue(vegetal, Vegetal)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Vegetal,
|
||||
Vegetal
|
||||
)
|
||||
}
|
||||
|
||||
@ -356,11 +361,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Earth
|
||||
]
|
||||
const validEarthOptions: Earth[] = Object.values(Earth)
|
||||
|
||||
if (typeof earth !== 'string' || !validEarthOptions.includes(earth)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-earth" are: [${validEarthOptions.join(', ')}]`
|
||||
if (earth && validateStringValue(earth, Earth)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Earth,
|
||||
Earth
|
||||
)
|
||||
}
|
||||
|
||||
@ -369,14 +375,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Microbial
|
||||
]
|
||||
const validMicrobialOptions: Microbial[] = Object.values(Microbial)
|
||||
|
||||
if (
|
||||
typeof microbial !== 'string' ||
|
||||
!validMicrobialOptions.includes(microbial)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-microbial" are: [${validMicrobialOptions.join(', ')}]`
|
||||
if (microbial && validateStringValue(microbial, Microbial)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Microbial,
|
||||
Microbial
|
||||
)
|
||||
}
|
||||
|
||||
@ -385,11 +389,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Oak
|
||||
]
|
||||
const validOakOptions: Oak[] = Object.values(Oak)
|
||||
|
||||
if (typeof oak !== 'string' || !validOakOptions.includes(oak)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-oak" are: [${validOakOptions.join(', ')}]`
|
||||
if (oak && validateStringValue(oak, Oak)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Oak,
|
||||
Oak
|
||||
)
|
||||
}
|
||||
|
||||
@ -398,14 +403,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Chocolate
|
||||
]
|
||||
const validChocolateOptions: Chocolate[] = Object.values(Chocolate)
|
||||
|
||||
if (
|
||||
typeof chocolate !== 'string' ||
|
||||
!validChocolateOptions.includes(chocolate)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-chocolate" are: [${validChocolateOptions.join(', ')}]`
|
||||
if (chocolate && validateStringValue(chocolate, Chocolate)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Chocolate,
|
||||
Chocolate
|
||||
)
|
||||
}
|
||||
|
||||
@ -414,14 +417,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Oxidation
|
||||
]
|
||||
const validOxidationOptions: Oxidation[] = Object.values(Oxidation)
|
||||
|
||||
if (
|
||||
typeof oxidation !== 'string' ||
|
||||
!validOxidationOptions.includes(oxidation)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-oxidation" are: [${validOxidationOptions.join(', ')}]`
|
||||
if (oxidation && validateStringValue(oxidation, Oxidation)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Oxidation,
|
||||
Oxidation
|
||||
)
|
||||
}
|
||||
|
||||
@ -430,11 +431,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Umami
|
||||
]
|
||||
const validUmamiOptions: Umami[] = Object.values(Umami)
|
||||
|
||||
if (typeof umami !== 'string' || !validUmamiOptions.includes(umami)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-umami" are: [${validUmamiOptions.join(', ')}]`
|
||||
if (umami && validateStringValue(umami, Umami)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Umami,
|
||||
Umami
|
||||
)
|
||||
}
|
||||
|
||||
@ -443,14 +445,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Balsamic
|
||||
]
|
||||
const validBalsamicOptions: Balsamic[] = Object.values(Balsamic)
|
||||
|
||||
if (
|
||||
typeof balsamic !== 'string' ||
|
||||
!validBalsamicOptions.includes(balsamic)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-balsamic" are: [${validBalsamicOptions.join(', ')}]`
|
||||
if (balsamic && validateStringValue(balsamic, Balsamic)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Balsamic,
|
||||
Balsamic
|
||||
)
|
||||
}
|
||||
|
||||
@ -459,11 +459,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Grain
|
||||
]
|
||||
const validGrainOptions: Grain[] = Object.values(Grain)
|
||||
|
||||
if (typeof grain !== 'string' || !validGrainOptions.includes(grain)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-grain" are: [${validGrainOptions.join(', ')}]`
|
||||
if (grain && validateStringValue(grain, Grain)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Grain,
|
||||
Grain
|
||||
)
|
||||
}
|
||||
|
||||
@ -472,11 +473,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Dairy
|
||||
]
|
||||
const validDairyOptions: Dairy[] = Object.values(Dairy)
|
||||
|
||||
if (typeof dairy !== 'string' || !validDairyOptions.includes(dairy)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-dairy" are: [${validDairyOptions.join(', ')}]`
|
||||
if (dairy && validateStringValue(dairy, Dairy)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Dairy,
|
||||
Dairy
|
||||
)
|
||||
}
|
||||
|
||||
@ -485,24 +487,18 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.PrimaryFlavoursAndAromas][
|
||||
PrimaryFlavoursAndAromasKey.Faults
|
||||
]
|
||||
const validFaultsOptions: (
|
||||
| Anisoles
|
||||
| Brettanomyces
|
||||
| VolatileAcidity
|
||||
| Reduction
|
||||
)[] = [
|
||||
...Object.values(Anisoles),
|
||||
...Object.values(Brettanomyces),
|
||||
...Object.values(VolatileAcidity),
|
||||
...Object.values(Reduction)
|
||||
]
|
||||
const validFaultsOptions = {
|
||||
...Anisoles,
|
||||
...Brettanomyces,
|
||||
...VolatileAcidity,
|
||||
...Reduction
|
||||
}
|
||||
|
||||
if (
|
||||
typeof faults !== 'string' ||
|
||||
!validFaultsOptions.includes(faults)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "visualAssessment-faults" are: [${validFaultsOptions.join(', ')}]`
|
||||
if (faults && validateStringValue(faults, validFaultsOptions)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.PrimaryFlavoursAndAromas,
|
||||
PrimaryFlavoursAndAromasKey.Faults,
|
||||
validFaultsOptions
|
||||
)
|
||||
}
|
||||
|
||||
@ -512,7 +508,9 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
const textureAndBalanceKeys = Object.keys(
|
||||
tastingNote[TastingNoteKey.TextureAndBalance]
|
||||
)
|
||||
const validTextureAndBalanceKeys = Object.values(TextureAndBalanceKey)
|
||||
const validTextureAndBalanceKeys = Object.values(
|
||||
TextureAndBalanceKey
|
||||
).filter((key) => key !== TextureAndBalanceKey.Age)
|
||||
|
||||
if (!compareArrays(textureAndBalanceKeys, validTextureAndBalanceKeys)) {
|
||||
return message(
|
||||
@ -525,14 +523,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.Sweetness
|
||||
]
|
||||
const validSweetnessOptions: Sweetness[] = Object.values(Sweetness)
|
||||
|
||||
if (
|
||||
typeof sweetness !== 'string' ||
|
||||
!validSweetnessOptions.includes(sweetness)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-sweetness" are: [${validSweetnessOptions.join(', ')}]`
|
||||
if (validateStringValue(sweetness, Sweetness)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.TextureAndBalance,
|
||||
TextureAndBalanceKey.Sweetness,
|
||||
Sweetness
|
||||
)
|
||||
}
|
||||
|
||||
@ -541,15 +537,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.Acidity
|
||||
]
|
||||
const validAcidityOptions: Concentration[] =
|
||||
Object.values(Concentration)
|
||||
|
||||
if (
|
||||
typeof acidity !== 'string' ||
|
||||
!validAcidityOptions.includes(acidity)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-acidity" are: [${validAcidityOptions.join(', ')}]`
|
||||
if (validateStringValue(acidity, Concentration)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.TextureAndBalance,
|
||||
TextureAndBalanceKey.Acidity,
|
||||
Concentration
|
||||
)
|
||||
}
|
||||
|
||||
@ -562,59 +555,67 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
const tanninKey = tanninKeys[0] as Concentration
|
||||
const validTanninKeys = Object.values(Concentration)
|
||||
|
||||
if (!isObject(tannin)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. "textureAndBalance-tannin" should be an object with the following properties: [${validTanninKeys.join(', ')}]`
|
||||
)
|
||||
}
|
||||
if (typeof tannin === 'string') {
|
||||
if (validateStringValue(tannin, TanninString)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.TextureAndBalance,
|
||||
TextureAndBalanceKey.Tannin,
|
||||
TanninString
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (!isObject(tannin)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. "textureAndBalance-tannin" should be an object with the following properties: [${validTanninKeys.join(', ')}]`
|
||||
)
|
||||
}
|
||||
|
||||
if (tanninKeys.length !== 1 || !validTanninKeys.includes(tanninKey)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-tannin" are: [${validTanninKeys.join(', ')}]`
|
||||
)
|
||||
}
|
||||
if (tanninKeys.length !== 1 || !validTanninKeys.includes(tanninKey)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-tannin" are: [${validTanninKeys.join(', ')}]`
|
||||
)
|
||||
}
|
||||
|
||||
// textureAndBalance-tannin-type validation
|
||||
const tanninType =
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.Tannin
|
||||
][tanninKey]
|
||||
const tanninTypeKeys = Object.keys(tanninType)
|
||||
const tanninTypeKey = tanninTypeKeys[0] as TanninType
|
||||
const validTanninTypeKeys = Object.values(TanninType)
|
||||
// textureAndBalance-tannin-type validation
|
||||
const tanninType = (
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.Tannin
|
||||
] as TanninObject
|
||||
)[tanninKey]
|
||||
const tanninTypeKeys = Object.keys(tanninType)
|
||||
const tanninTypeKey = tanninTypeKeys[0] as TanninType
|
||||
const validTanninTypeKeys = Object.values(TanninType)
|
||||
|
||||
if (!isObject(tanninType)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. "textureAndBalance-tannin-type" should be an object with the following properties: [${validTanninTypeKeys.join(', ')}]`
|
||||
)
|
||||
}
|
||||
if (!isObject(tanninType)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. "textureAndBalance-tannin-type" should be an object with the following properties: [${validTanninTypeKeys.join(', ')}]`
|
||||
)
|
||||
}
|
||||
|
||||
if (
|
||||
tanninTypeKeys.length !== 1 ||
|
||||
!validTanninTypeKeys.includes(tanninTypeKey)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-tannin-type" are: [${validTanninTypeKeys.join(', ')}]`
|
||||
)
|
||||
}
|
||||
if (
|
||||
tanninTypeKeys.length !== 1 ||
|
||||
!validTanninTypeKeys.includes(tanninTypeKey)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-tannin-type" are: [${validTanninTypeKeys.join(', ')}]`
|
||||
)
|
||||
}
|
||||
|
||||
// textureAndBalance-tannin-value validation
|
||||
const tanninValue =
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.Tannin
|
||||
][tanninKey][tanninTypeKey]
|
||||
const validTanninValueOptions = [
|
||||
...Object.values(RipeTannin),
|
||||
...Object.values(UnripeTannin)
|
||||
]
|
||||
// textureAndBalance-tannin-value validation
|
||||
const tanninValue = (
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.Tannin
|
||||
] as TanninObject
|
||||
)[tanninKey][tanninTypeKey]
|
||||
const validTanninValueOptions = { ...RipeTannin, ...UnripeTannin }
|
||||
|
||||
if (
|
||||
typeof tanninValue !== 'string' ||
|
||||
!validTanninValueOptions.includes(tanninValue)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-tannin-type-value" are: [${validTanninValueOptions.join(', ')}]`
|
||||
)
|
||||
if (validateStringValue(tanninValue, validTanninValueOptions)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.TextureAndBalance,
|
||||
TextureAndBalanceKey.Tannin,
|
||||
validTanninValueOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// textureAndBalance-alcohol validation
|
||||
@ -622,15 +623,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.Alcohol
|
||||
]
|
||||
const validAlcoholOptions: Concentration[] =
|
||||
Object.values(Concentration)
|
||||
|
||||
if (
|
||||
typeof alcohol !== 'string' ||
|
||||
!validAlcoholOptions.includes(alcohol)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-alcohol" are: [${validAlcoholOptions.join(', ')}]`
|
||||
if (validateStringValue(alcohol, Concentration)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.TextureAndBalance,
|
||||
TextureAndBalanceKey.Alcohol,
|
||||
Concentration
|
||||
)
|
||||
}
|
||||
|
||||
@ -639,11 +637,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.Body
|
||||
]
|
||||
const validBodyOptions: Body[] = Object.values(Body)
|
||||
|
||||
if (typeof body !== 'string' || !validBodyOptions.includes(body)) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-body" are: [${validBodyOptions.join(', ')}]`
|
||||
if (validateStringValue(body, Body)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.TextureAndBalance,
|
||||
TextureAndBalanceKey.Body,
|
||||
Body
|
||||
)
|
||||
}
|
||||
|
||||
@ -652,15 +651,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.FlavourIntensity
|
||||
]
|
||||
const validFlavourIntensityOptions: FlavourIntensity[] =
|
||||
Object.values(FlavourIntensity)
|
||||
|
||||
if (
|
||||
typeof flavourIntensity !== 'string' ||
|
||||
!validFlavourIntensityOptions.includes(flavourIntensity)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-flavourIntensity" are: [${validFlavourIntensityOptions.join(', ')}]`
|
||||
if (validateStringValue(flavourIntensity, FlavourIntensity)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.TextureAndBalance,
|
||||
TextureAndBalanceKey.FlavourIntensity,
|
||||
FlavourIntensity
|
||||
)
|
||||
}
|
||||
|
||||
@ -669,15 +665,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.PalateLength
|
||||
]
|
||||
const validPalateLengthOptions: PalateLength[] =
|
||||
Object.values(PalateLength)
|
||||
|
||||
if (
|
||||
typeof palateLength !== 'string' ||
|
||||
!validPalateLengthOptions.includes(palateLength)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-palateLength" are: [${validPalateLengthOptions.join(', ')}]`
|
||||
if (validateStringValue(palateLength, PalateLength)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.TextureAndBalance,
|
||||
TextureAndBalanceKey.PalateLength,
|
||||
PalateLength
|
||||
)
|
||||
}
|
||||
|
||||
@ -751,26 +744,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.Quality
|
||||
]
|
||||
const validQualityOptions: Quality[] = Object.values(Quality)
|
||||
|
||||
if (
|
||||
typeof quality !== 'string' ||
|
||||
!validQualityOptions.includes(quality)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-quality" are: [${validQualityOptions.join(', ')}]`
|
||||
)
|
||||
}
|
||||
|
||||
// textureAndBalance-age validation
|
||||
const textureAndBalanceKeyAge =
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.Age
|
||||
]
|
||||
|
||||
if (typeof textureAndBalanceKeyAge !== 'number') {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-reasoning-age" should be a number`
|
||||
if (validateStringValue(quality, Quality)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.TextureAndBalance,
|
||||
TextureAndBalanceKey.Quality,
|
||||
Quality
|
||||
)
|
||||
}
|
||||
|
||||
@ -779,15 +758,12 @@ export const reviewValidation = (data: unknown): Joi.ValidationResult =>
|
||||
tastingNote[TastingNoteKey.TextureAndBalance][
|
||||
TextureAndBalanceKey.ReadinessToDrink
|
||||
]
|
||||
const validReadinessToDrinkOptions: ReadinessToDrink[] =
|
||||
Object.values(ReadinessToDrink)
|
||||
|
||||
if (
|
||||
typeof readinessToDrink !== 'string' ||
|
||||
!validReadinessToDrinkOptions.includes(readinessToDrink)
|
||||
) {
|
||||
return message(
|
||||
`provided "tastingNote" is not valid. Valid options for "textureAndBalance-readinessToDrink" are: [${validReadinessToDrinkOptions.join(', ')}]`
|
||||
if (validateStringValue(readinessToDrink, ReadinessToDrink)) {
|
||||
return messageWithValidOptions(
|
||||
TastingNoteKey.TextureAndBalance,
|
||||
TextureAndBalanceKey.ReadinessToDrink,
|
||||
ReadinessToDrink
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -245,10 +245,10 @@ export const spiritValidation = (data: unknown): Joi.ValidationResult =>
|
||||
})
|
||||
}
|
||||
|
||||
const spiritType: SpiritType = helper.state.ancestors[1].type
|
||||
const spiritType: SpiritType = helper.state.ancestors[0].type
|
||||
|
||||
const spiritVariant: string | { [key: string]: unknown } =
|
||||
helper.state.ancestors[1].variant
|
||||
helper.state.ancestors[0].variant
|
||||
|
||||
const spiritVariantName =
|
||||
typeof spiritVariant === 'string'
|
||||
|
@ -36,3 +36,8 @@ export const RRPcurrencyValidation = Joi.string().length(3).required()
|
||||
export const descriptionValidation = Joi.string().required()
|
||||
export const urlValidation = Joi.string()
|
||||
export const imageValidation = Joi.string()
|
||||
|
||||
export const validateStringValue = (
|
||||
value: unknown,
|
||||
validOptions: { [key: string]: string }
|
||||
) => typeof value !== 'string' || !Object.values(validOptions).includes(value)
|
||||
|
@ -302,7 +302,7 @@ export const wineValidation = (data: unknown): Joi.ValidationResult =>
|
||||
style: Joi.string()
|
||||
.valid(...Object.values(WineStyle))
|
||||
.required(),
|
||||
characteristic: Joi.string().custom((value: string[], helper) => {
|
||||
characteristic: Joi.string().custom((value, helper) => {
|
||||
// return if no value
|
||||
if (!value) {
|
||||
return value
|
||||
@ -359,14 +359,12 @@ export const wineValidation = (data: unknown): Joi.ValidationResult =>
|
||||
})
|
||||
}
|
||||
|
||||
for (const characteristic of value) {
|
||||
if (!options.includes(characteristic)) {
|
||||
return helper.message({
|
||||
custom: Joi.expression(
|
||||
`"${characteristic}" is not a valid characteristic for "${wineType}" wine. Valid options are [${options.map((option) => `"${option}"`).join(', ')}]`
|
||||
)
|
||||
})
|
||||
}
|
||||
if (!options.includes(value)) {
|
||||
return helper.message({
|
||||
custom: Joi.expression(
|
||||
`"${value}" is not a valid characteristic for "${wineType}" wine. Valid options are [${options.map((option) => `"${option}"`).join(', ')}]`
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
return value
|
||||
|
Loading…
x
Reference in New Issue
Block a user