misc work
This commit is contained in:
parent
80261bc524
commit
7b7b1c5ad4
@ -2,5 +2,6 @@ import { defineConfig } from 'histoire';
|
||||
import { HstSvelte } from '@histoire/plugin-svelte';
|
||||
|
||||
export default defineConfig({
|
||||
setupFile: '/src/histoire.setup.js',
|
||||
plugins: [HstSvelte()],
|
||||
});
|
||||
|
1
src/histoire.setup.js
Normal file
1
src/histoire.setup.js
Normal file
@ -0,0 +1 @@
|
||||
//global?.__SVELTEKIT_APP_VERSION_POLL_INTERVAL__ = 1000;
|
@ -1,5 +0,0 @@
|
||||
<script>
|
||||
import 'beercss';
|
||||
</script>
|
||||
|
||||
; // import 'material-dynamic-colors';
|
25
src/lib/components/Battle.story.svelte
Normal file
25
src/lib/components/Battle.story.svelte
Normal file
@ -0,0 +1,25 @@
|
||||
<Beer />
|
||||
<Hst.Story>
|
||||
<Battle {status} />
|
||||
|
||||
<svelte:fragment slot="controls">
|
||||
<Hst.Select
|
||||
bind:value={status}
|
||||
title="status"
|
||||
options={Object.fromEntries(statuses.map((s) => [s, s]))}
|
||||
/>
|
||||
<Hst.Number bind:value={wave} title="wave" />
|
||||
</svelte:fragment>
|
||||
</Hst.Story>
|
||||
|
||||
<script>
|
||||
/** @type any */
|
||||
export let Hst;
|
||||
import Beer from './Beer.svelte';
|
||||
import Battle from './Battle.svelte';
|
||||
|
||||
let status = 'upcoming';
|
||||
let wave = '1';
|
||||
|
||||
let statuses = ['upcoming', 'prep', 'ongoing', 'won', 'lost'];
|
||||
</script>
|
124
src/lib/components/Battle.svelte
Normal file
124
src/lib/components/Battle.svelte
Normal file
@ -0,0 +1,124 @@
|
||||
<h5><a href={`#/campaign/${params.campaignId}`}>{$activeCampaign?.name}</a></h5>
|
||||
<h6>Chapter {chapter}, battle {chapterBattle} -- {status}</h6>
|
||||
<dl>
|
||||
{#if status === 'ongoing'}
|
||||
<dt>wave</dt>
|
||||
<dd>{wave === 2 ? 'second' : 'first'}</dd>
|
||||
{/if}
|
||||
<dt>city</dt>
|
||||
<dd>{city}</dd>
|
||||
<dt>scenario</dt>
|
||||
<dd>{scenario}</dd>
|
||||
<dt>character</dt>
|
||||
<dd>{character}</dd>
|
||||
|
||||
<dt>difficulty</dt>
|
||||
<dd>
|
||||
<div class="field border">
|
||||
<input
|
||||
type="number"
|
||||
step="0.5"
|
||||
value={difficulty}
|
||||
on:change={({ target: { value } }) =>
|
||||
event.setBattleDifficulty(params.battleId, value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<Stars
|
||||
on:change={(e) => (difficulty = e.target.value)}
|
||||
config={{
|
||||
readOnly: false, //status !== 'preparation',
|
||||
countStars: 5,
|
||||
score: difficulty,
|
||||
showScore: false,
|
||||
starConfig: {
|
||||
size: 15,
|
||||
fillColor: '#F9ED4F',
|
||||
strokeColor: '#BB8511',
|
||||
unfilledColor: '#FFF',
|
||||
strokeUnfilledColor: '#000',
|
||||
},
|
||||
range: { min: 0, max: 5, step: 0.5 },
|
||||
}}
|
||||
/>
|
||||
{difficulty}
|
||||
-->
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
{#if status === 'upcoming'}
|
||||
<button>Start battle</button>
|
||||
{:else if status === 'ongoing'}
|
||||
<button on:click={battleVerdict('won')}>Battle won</button>
|
||||
<button on:click={battleVerdict('lost')}>Battle lost</button>
|
||||
{/if}
|
||||
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
import Stars from '@ernane/svelte-star-rating';
|
||||
|
||||
export let params;
|
||||
|
||||
const { activeCampaign, event } = getContext('api');
|
||||
|
||||
event.setActiveCampaign(params.campaignId);
|
||||
|
||||
$: battles = $activeCampaign?.battles;
|
||||
$: battle = battles && battles[params.battleId - 1];
|
||||
$: console.log($activeCampaign);
|
||||
$: scenario = battle?.scenario;
|
||||
$: status = battle?.status;
|
||||
$: wave = battle?.wave;
|
||||
$: difficulty = battle?.difficulty ?? 0;
|
||||
$: character = battle?.character;
|
||||
$: city = battle?.city;
|
||||
|
||||
$: console.log(battle);
|
||||
|
||||
let chapter = 1 + parseInt(params.battleId / 2);
|
||||
let chapterBattle = params.battleId % 2;
|
||||
|
||||
const battleVerdict = (verdict) =>
|
||||
event.setBattleVerdict(params.battleId, verdict);
|
||||
|
||||
// $: event.setBattleDifficulty(params.battleId, difficulty);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
article {
|
||||
width: 500px;
|
||||
}
|
||||
header {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
h5 {
|
||||
flex: 1;
|
||||
}
|
||||
h6 {
|
||||
font-style: italic;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
dl {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 8em auto;
|
||||
grid-row-gap: 0.75em;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
dt {
|
||||
text-align: right;
|
||||
padding-right: 2em;
|
||||
}
|
||||
dd {
|
||||
display: flex;
|
||||
}
|
||||
article :global(.stars-container) {
|
||||
justify-content: left !important;
|
||||
margin-right: 1em;
|
||||
}
|
||||
input {
|
||||
width: 5em;
|
||||
}
|
||||
</style>
|
64
src/lib/components/Campaign.svelte
Normal file
64
src/lib/components/Campaign.svelte
Normal file
@ -0,0 +1,64 @@
|
||||
<article>
|
||||
{#if $activeCampaign}
|
||||
<h5>{$activeCampaign.name}</h5>
|
||||
<h6>Chapter 1</h6>
|
||||
<Battle {...battles[0]} {campaignId} chapter={1} chapterBattle={1} />
|
||||
<div class="medium-divider" />
|
||||
<Battle {...battles[1]} {campaignId} chapter={1} chapterBattle={2} />
|
||||
<div class="medium-divider" {campaignId} />
|
||||
<h6>Chapter 2</h6>
|
||||
<Battle {...battles[2]} {campaignId} chapter={2} chapterBattle={1} />
|
||||
<div class="medium-divider" />
|
||||
<Battle {...battles[3]} {campaignId} chapter={2} chapterBattle={2} />
|
||||
<div class="medium-divider" />
|
||||
<h6>Chapter 3</h6>
|
||||
<Battle {...battles[4]} {campaignId} chapter={3} chapterBattle={1} />
|
||||
<div class="medium-divider" />
|
||||
<Battle {...battles[5]} {campaignId} chapter={3} chapterBattle={2} />
|
||||
<div class="medium-divider" />
|
||||
<h6>Chapter 4</h6>
|
||||
<Battle {...battles[6]} {campaignId} chapter={4} chapterBattle={1} />
|
||||
<div class="medium-divider" />
|
||||
<Battle {...battles[7]} {campaignId} chapter={4} chapterBattle={2} />
|
||||
<div class="medium-divider" />
|
||||
<Battle {...battles[8]} {campaignId} chapter={4} chapterBattle={3} />
|
||||
<div class="medium-divider" />
|
||||
<Battle {...battles[9]} {campaignId} chapter={4} chapterBattle={4} />
|
||||
<div class="medium-divider" />
|
||||
<Battle {...battles[10]} {campaignId} chapter={4} chapterBattle={5} />
|
||||
<div class="medium-divider" />
|
||||
<Battle {...battles[11]} {campaignId} chapter={4} chapterBattle={6} />
|
||||
<div class="medium-divider" />
|
||||
{/if}
|
||||
</article>
|
||||
|
||||
<script>
|
||||
import * as R from 'remeda';
|
||||
import Battle from './Campaign/Battle.svelte';
|
||||
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
export let params;
|
||||
|
||||
const api = getContext('api');
|
||||
|
||||
api.event.setActiveCampaign(params.campaignId);
|
||||
|
||||
const { activeCampaign } = getContext('api');
|
||||
|
||||
$: battles = $activeCampaign?.battles ?? [];
|
||||
|
||||
$: while (battles.length <= 12) battles.push({ notYet: true });
|
||||
|
||||
const campaignId = params.campaignId;
|
||||
|
||||
$: byChapter = R.pipe(
|
||||
$activeCampaign?.battles ?? [],
|
||||
R.groupBy(({ id }) => R.clamp(1 + parseInt(id / 2), { max: 4 })),
|
||||
);
|
||||
|
||||
$: console.log(byChapter);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
24
src/lib/components/Campaign/Battle.svelte
Normal file
24
src/lib/components/Campaign/Battle.svelte
Normal file
@ -0,0 +1,24 @@
|
||||
<div class="row">
|
||||
<p>
|
||||
{#if notYet}
|
||||
???
|
||||
{:else}
|
||||
<a href={`#/campaign/${campaignId}/battle/${id}`}>
|
||||
Battle of {city}</a
|
||||
><span>, {status}</span>
|
||||
{/if}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
export let city = '';
|
||||
export let status = '';
|
||||
export let id = 0;
|
||||
export let notYet = false;
|
||||
export let campaignId;
|
||||
export let chapter;
|
||||
export let chapterBattle;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
@ -5,9 +5,21 @@
|
||||
</Hst.Story>
|
||||
|
||||
<script>
|
||||
import { setContext } from 'svelte';
|
||||
|
||||
export let Hst;
|
||||
import Beer from './Beer.svelte';
|
||||
import Campaigns from './Campaigns.svelte';
|
||||
import { genApi } from '$lib/store/api.js';
|
||||
|
||||
global.__SVELTEKIT_APP_VERSION_POLL_INTERVAL__ = 1000;
|
||||
|
||||
const campaigns = [{ name: 'Earth 613' }];
|
||||
|
||||
setContext(
|
||||
'api',
|
||||
genApi({
|
||||
local: campaigns,
|
||||
}),
|
||||
);
|
||||
</script>
|
||||
|
@ -4,12 +4,12 @@
|
||||
<button on:click={newCampaign}>new campaign</button>
|
||||
</header>
|
||||
|
||||
{#each campaigns as campaign (campaign.id)}
|
||||
{#each $campaigns as campaign (campaign.id)}
|
||||
<div class="row">
|
||||
<i class="light-green-text">south_america</i>
|
||||
<div class="max">
|
||||
<h6>
|
||||
<a href={`/campaign/${campaign.id}`}>
|
||||
<a href={`#/campaign/${campaign._id}`}>
|
||||
{campaign.name}
|
||||
</a>
|
||||
</h6>
|
||||
@ -50,10 +50,11 @@
|
||||
<script>
|
||||
import * as R from 'remeda';
|
||||
import { getContext } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
// import { goto } from '$app/navigation';
|
||||
const goto = () => {};
|
||||
|
||||
export let campaigns = [];
|
||||
export let api = getContext('api');
|
||||
export let campaigns = api?.campaigns;
|
||||
|
||||
let showNewCampaign = false;
|
||||
let newCampaignName = '';
|
||||
|
@ -1,47 +1,124 @@
|
||||
import PouchDB from 'pouchdb-browser';
|
||||
import * as R from 'remeda';
|
||||
import Dexie, { liveQuery } from 'dexie';
|
||||
import { writable, derived } from 'svelte/store';
|
||||
import { writable, derived, get } from 'svelte/store';
|
||||
import { genNextBattle } from './genNextBattle.js';
|
||||
import u from '@yanick/updeep-remeda';
|
||||
|
||||
const seedCampaign = {
|
||||
battles: [],
|
||||
};
|
||||
|
||||
export function genApi(options = {}) {
|
||||
const storage = new Dexie('Campaigns', options.dexie ?? {});
|
||||
const pouchdb = new PouchDB(
|
||||
'Campaigns',
|
||||
options.local
|
||||
? {
|
||||
adapter: 'memory',
|
||||
}
|
||||
: {},
|
||||
);
|
||||
|
||||
storage.version(1).stores({
|
||||
campaigns: '++id,name',
|
||||
const campaignsCore = writable([]);
|
||||
|
||||
pouchdb
|
||||
.allDocs({ include_docs: true })
|
||||
.then((r) => r.rows.map(({ id, doc }) => [id, doc]))
|
||||
.then(Object.fromEntries)
|
||||
.then(campaignsCore.set);
|
||||
|
||||
pouchdb
|
||||
.changes({ since: 'now', live: true, include_docs: true })
|
||||
.on('change', (change) => {
|
||||
console.log({ change });
|
||||
if (change.deleted) {
|
||||
campaignsCore.update(u.skip(change.id));
|
||||
} else {
|
||||
campaignsCore.update(u.updateIn(change.id, change.doc));
|
||||
}
|
||||
});
|
||||
|
||||
const campaigns = writable([]);
|
||||
storage.campaigns.toArray().then((c) => campaigns.set(c));
|
||||
const campaigns = derived(campaignsCore, Object.values);
|
||||
campaigns.subscribe((c) => console.log(c));
|
||||
|
||||
const activeCampaignId = writable();
|
||||
const addCampaign = (name) =>
|
||||
pouchdb.post({
|
||||
name,
|
||||
...seedCampaign,
|
||||
battles: [{ id: 1, ...genNextBattle() }],
|
||||
});
|
||||
|
||||
const activeCampaignId = writable(0);
|
||||
|
||||
const setActiveCampaign = activeCampaignId.set;
|
||||
|
||||
const activeCampaign = derived(
|
||||
[activeCampaignId, campaigns],
|
||||
async ([id, campaigns], set) => {
|
||||
const x = campaigns.find((c) => c.id === id);
|
||||
set(x);
|
||||
},
|
||||
[campaignsCore, activeCampaignId],
|
||||
([$c, $id]) => $c[$id],
|
||||
);
|
||||
|
||||
const setBattleDifficulty = (battleId, difficulty) => {
|
||||
pouchdb
|
||||
.put(
|
||||
u.updateIn(get(activeCampaign), `battles.${battleId - 1}`, {
|
||||
difficulty,
|
||||
}),
|
||||
)
|
||||
.catch((e) => console.error(e));
|
||||
};
|
||||
|
||||
const setBattleVerdict = (battleId, status) => {
|
||||
let campaign = get(activeCampaign);
|
||||
|
||||
campaign = u.updateIn(campaign, `battles.${battleId - 1}`, {
|
||||
status,
|
||||
});
|
||||
|
||||
campaign = u(campaign, {
|
||||
battles: (battles) => [
|
||||
...battles,
|
||||
u(genNextBattle(campaign.battles), {
|
||||
id: battles.length + 1,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
pouchdb.put(campaign).catch((e) => console.error(e));
|
||||
};
|
||||
|
||||
return {
|
||||
campaigns,
|
||||
activeCampaign,
|
||||
storage,
|
||||
event: {
|
||||
addCampaign,
|
||||
setActiveCampaign,
|
||||
setBattleVerdict,
|
||||
setBattleDifficulty,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
const activeCampaign = writeable();
|
||||
|
||||
addCampaign: (name) =>
|
||||
storage.campaigns.add({
|
||||
name,
|
||||
...seedCampaign,
|
||||
battles: [genNextBattle()],
|
||||
battles: [{ id: 1, ...genNextBattle() }],
|
||||
}),
|
||||
|
||||
return {
|
||||
campaigns,
|
||||
event: {
|
||||
,
|
||||
addCampaign: (name) =>
|
||||
storage.campaigns.add({
|
||||
name,
|
||||
...seedCampaign,
|
||||
battles: [{ id: 1, ...genNextBattle() }],
|
||||
}),
|
||||
deleteCampaign: (id) => storage.campaigns.delete(id),
|
||||
setActiveCampaign: async (id) => {
|
||||
activeCampaignId.set(id);
|
||||
},
|
||||
},
|
||||
};
|
||||
*/
|
||||
}
|
||||
|
@ -23,6 +23,6 @@ export function genNextBattle(battles = []) {
|
||||
),
|
||||
);
|
||||
|
||||
return { scenario, character, city, status: 'upcoming' };
|
||||
return { scenario, character, city, status: 'ongoing', wave: 1 };
|
||||
}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
export const ssr = false;
|
@ -1,15 +0,0 @@
|
||||
<article>
|
||||
{#if $activeCampaign}
|
||||
<h5>{$activeCampaign.name}</h5>
|
||||
<h6>Chapter 1</h6>
|
||||
<ul>
|
||||
<li>Battle of New York, ongoing</li>
|
||||
</ul>
|
||||
{/if}
|
||||
</article>
|
||||
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
const { activeCampaign } = getContext('api');
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user