202 lines
4.6 KiB
TypeScript
202 lines
4.6 KiB
TypeScript
import { error, redirect, type Action, type Actions } from '@sveltejs/kit';
|
|
import type { PageServerLoad } from './$types';
|
|
import { createAdventureApiAdventuresPost, getUserProfileBffUserProfileGet } from '@client';
|
|
import * as v from 'valibot';
|
|
import { randomItemInArray, shuffleArray } from '$lib';
|
|
import { formatLanguage } from '$lib/formatters';
|
|
|
|
const allVibes = [
|
|
'Melancholic',
|
|
'Gothic',
|
|
'Sun-drenched',
|
|
'Bleak',
|
|
'Whimsical',
|
|
'Eerie',
|
|
'Cosy',
|
|
'Tense',
|
|
'Witty',
|
|
'Propulsive',
|
|
'Mentor and student',
|
|
'Unlikely duo',
|
|
'Lone wolf',
|
|
'Queer-norm',
|
|
'Class tensions',
|
|
'Chosen family',
|
|
'Diaspora',
|
|
'Academia',
|
|
'Small town',
|
|
'The sea',
|
|
'Grand house',
|
|
'Road trip',
|
|
'A single night',
|
|
'Heist',
|
|
'Mystery box',
|
|
'Reluctant hero',
|
|
'Redemption',
|
|
'Animal companions',
|
|
'Gentle',
|
|
'Happy ever after',
|
|
'Bittersweet',
|
|
'Epistolary (letters / diary entries)',
|
|
"A big city that isn't the capital",
|
|
'Parenthood',
|
|
'Sly',
|
|
'Slapstick',
|
|
'Recovery',
|
|
'Political',
|
|
'Apocalyptic',
|
|
'Post-apocalyptic',
|
|
'Survival',
|
|
'War',
|
|
'Spy thriller',
|
|
'Time travel'
|
|
];
|
|
|
|
const allGenres = [
|
|
'Crime Fiction',
|
|
'Crime noir',
|
|
'Who-dun-it mystery',
|
|
'Paranormal',
|
|
'Horror',
|
|
'Psychological thriller',
|
|
'Romance',
|
|
'Family',
|
|
'Fantasy',
|
|
'Science Fiction'
|
|
];
|
|
export const load: PageServerLoad = async ({ locals }) => {
|
|
let languageCode = 'fr';
|
|
let competency = 'A1';
|
|
|
|
const profile = await getUserProfileBffUserProfileGet({
|
|
headers: {
|
|
Authorization: `Bearer ${locals.authToken}`
|
|
}
|
|
});
|
|
|
|
if (profile.error) {
|
|
console.error({ error: profile.error });
|
|
} else {
|
|
languageCode = profile.data?.learnable_languages[0].target_language ?? 'fr';
|
|
competency = profile.data?.learnable_languages[0].proficiencies[0] ?? competency;
|
|
}
|
|
return {
|
|
lengths: ['100-200 Words', '200-350 Words', '350-500 Words', '500-750 Words'],
|
|
competency: competency,
|
|
language: {
|
|
code: languageCode,
|
|
label: formatLanguage(languageCode)
|
|
},
|
|
competencies: ['A1', 'A2', 'B1', 'B2', 'C1'],
|
|
languages: [
|
|
{ code: 'fr', name: 'French' },
|
|
{ code: 'de', name: 'German' },
|
|
{ code: 'it', name: 'Italian' },
|
|
{ code: 'es', name: 'Spanish' },
|
|
{ code: 'pt', name: 'Portuguese' }
|
|
],
|
|
genres: allGenres.sort((a, b) => a.localeCompare(b)),
|
|
selectedGenre: randomItemInArray(allGenres),
|
|
eras: [
|
|
'Ancient/Classical',
|
|
'Medieval',
|
|
'1500-1800',
|
|
'Renaissance',
|
|
'19th century',
|
|
'Early 20th century',
|
|
'Mid-century',
|
|
'Contemporary',
|
|
'Near future',
|
|
'Far future'
|
|
],
|
|
settings: [
|
|
'Capital city',
|
|
'Large city (not the capital)',
|
|
'Urban',
|
|
'The suburbs',
|
|
'Rural',
|
|
'Pastoral',
|
|
'Small town',
|
|
'Wilderness',
|
|
'Space',
|
|
'Another planet'
|
|
],
|
|
allVibes: allVibes,
|
|
selectedVibes: shuffleArray(allVibes)
|
|
.slice(0, 6)
|
|
.sort((a, b) => a.localeCompare(b))
|
|
};
|
|
};
|
|
|
|
const CreateFormSchema = v.object({
|
|
vibes: v.array(v.string()),
|
|
genre: v.string(),
|
|
setting: v.string(),
|
|
competency: v.pipe(v.string(), v.picklist(['A1', 'A2', 'B1', 'B2', 'C1'])),
|
|
language: v.pipe(v.string(), v.picklist(['fr', 'it', 'de', 'it', 'es'])),
|
|
length: v.string(),
|
|
protagonist_gender: v.string(),
|
|
protagonist_age: v.string()
|
|
});
|
|
|
|
export const actions = {
|
|
default: async ({ locals, request }) => {
|
|
const { authToken } = locals;
|
|
|
|
const formData = await request.formData();
|
|
|
|
const data = v.safeParse(CreateFormSchema, {
|
|
vibes: formData.getAll('vibes') as string[],
|
|
genre: formData.get('genre') as string,
|
|
setting: formData.get('setting') as string,
|
|
competency: formData.get('competency') as string,
|
|
language: formData.get('language') as string,
|
|
length: formData.get('length') as string,
|
|
protagonist_gender: formData.get('protagonist_gender') as string,
|
|
protagonist_age: formData.get('protagonist_age') as string
|
|
});
|
|
|
|
if (data.success == false) {
|
|
console.error({ formError: data.issues });
|
|
throw error(400, {
|
|
message: data.issues.map((e) => `${e.path?.[0].key}: ${e.message}`).join(', ')
|
|
});
|
|
}
|
|
|
|
const {
|
|
competency,
|
|
language,
|
|
length,
|
|
genre,
|
|
setting,
|
|
protagonist_gender,
|
|
protagonist_age,
|
|
vibes
|
|
} = data.output;
|
|
|
|
const { data: apiData, error: apiError } = await createAdventureApiAdventuresPost({
|
|
headers: {
|
|
Authorization: `Bearer ${authToken}`
|
|
},
|
|
body: {
|
|
competencies: [competency],
|
|
language: language,
|
|
genres: [genre],
|
|
setting: [setting],
|
|
vibes: vibes,
|
|
protagonist: [protagonist_gender, protagonist_age],
|
|
source_language: 'en',
|
|
entry_word_count_range: length,
|
|
max_entry_count: 6
|
|
}
|
|
});
|
|
|
|
if (apiError) {
|
|
return {
|
|
error: `Error creating new adventure, try again`
|
|
};
|
|
}
|
|
|
|
redirect(303, '/app/adventures?created=true');
|
|
}
|
|
} satisfies Actions;
|