Add detail to wish counter

pull/1/head
I Made Setia Baruna 2021-02-01 01:56:26 +08:00
parent 8d3fd97d6b
commit 932f03e377
5 changed files with 317 additions and 36 deletions

View File

@ -6,7 +6,7 @@
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
export let className; export let className = '';
export let icon = null; export let icon = null;
export let options; export let options;
export let placeholder = 'Select...'; export let placeholder = 'Select...';

View File

@ -0,0 +1,107 @@
<script>
import { onMount } from 'svelte';
import dayjs from 'dayjs';
import Select from '../components/Select.svelte';
import CharacterSelect from '../components/CharacterSelect.svelte';
import WeaponSelect from '../components/WeaponSelect.svelte';
import Input from '../components/Input.svelte';
import Button from './Button.svelte';
import { weaponList } from '../data/weaponList';
import { characters } from '../data/characters';
export let addPullDetail = () => {};
export let editPullDetail = () => {};
export let deletePullDetail = () => {};
export let pity;
export let skip;
export let isEdit = false;
export let editType = '';
export let editName = '';
export let editTime = '';
let selectOptions = [
{ label: 'Character', value: 'character' },
{ label: 'Weapon', value: 'weapon' },
];
let type;
let name;
let time = dayjs().format('YYYY-MM-DDTHH:mm');
onMount(() => {
if (!isEdit) return;
type = selectOptions.find((e) => e.value === editType);
if (editType === 'character') {
name = characters[editName];
} else {
name = weaponList[editName];
}
time = dayjs.unix(editTime).format('YYYY-MM-DDTHH:mm');
});
function add() {
const pull = {
type: type.value,
id: name.id,
time: dayjs(time).unix(),
pity,
};
addPullDetail(pull);
}
function edit() {
const pull = {
type: type.value,
id: name.id,
time: dayjs(time).unix(),
pity,
};
editPullDetail(pull);
}
function deleteDetail() {
deletePullDetail();
}
$: disabled = !name || !time;
</script>
<div class="text-white">
<p class="font-display font-bold mb-4">Add Pull Detail</p>
<Select options={selectOptions} bind:selected={type} placeholder="Select Type..." />
<div class="h-4" />
{#if type && type.value === 'weapon'}
<WeaponSelect bind:selected={name} />
{:else}
<CharacterSelect bind:selected={name} />
{/if}
<div class="h-4" />
<Input type="datetime-local" bind:value={time} />
<div class="h-4" />
<div class="flex items-center">
<p class="ml-4 mr-4">At Pity:</p>
<Input type="number" bind:value={pity} />
</div>
{#if isEdit}
<div class="flex mt-32">
<div class="flex-1 flex mr-2 items-end">
<Button className="flex-1" on:click={skip}>Cancel</Button>
</div>
<div class="flex-1 flex flex-col ml-2">
<Button className="flex-1" color="red" on:click={deleteDetail}>Delete</Button>
<Button className="flex-1 mt-2" {disabled} on:click={edit}>Save</Button>
</div>
</div>
{:else}
<div class="flex mt-32">
<Button className="flex-1 mr-2" color="red" on:click={skip}>Skip</Button>
<Button className="flex-1 ml-2" {disabled} on:click={add}>Add</Button>
</div>
{/if}
</div>

View File

@ -11,44 +11,62 @@
Press Press
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center">+1</b> <b class="rounded-lg px-2 py-1 border-white border inline-flex items-center">+1</b>
when you get when you get
<span class="inline-flex items-center">3 <span class="inline-flex items-center"
<Icon path={mdiStar} size={0.7} /></span> >3
<Icon path={mdiStar} size={0.7} /></span
>
</p> </p>
<p class="mb-2"> <p class="mb-2">
Press Press
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center">Get 4 <b class="rounded-lg px-2 py-1 border-white border inline-flex items-center"
<Icon path={mdiStar} size={0.7} /></b> >Get 4
<Icon path={mdiStar} size={0.7} /></b
>
when you get when you get
<span class="inline-flex items-center">4 <span class="inline-flex items-center"
<Icon path={mdiStar} size={0.7} /></span> >4
<Icon path={mdiStar} size={0.7} /></span
>
</p> </p>
<p class="mb-2"> <p class="mb-2">
Press Press
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center">Get 5 <b class="rounded-lg px-2 py-1 border-white border inline-flex items-center"
<Icon path={mdiStar} size={0.7} /></b> >Get 5
<Icon path={mdiStar} size={0.7} /></b
>
when you get when you get
<span class="inline-flex items-center">5 <span class="inline-flex items-center"
<Icon path={mdiStar} size={0.7} /></span> >5
<Icon path={mdiStar} size={0.7} /></span
>
</p> </p>
<p class="text-gray-400"> <p class="text-gray-400">
It will automatically add the lifetime pulls, It will automatically add the lifetime pulls,
<span class="inline-flex items-center">5 <span class="inline-flex items-center"
<Icon path={mdiStar} size={0.7} /></span> >5
<Icon path={mdiStar} size={0.7} /></span
>
and and
<span class="inline-flex items-center">4 <span class="inline-flex items-center"
<Icon path={mdiStar} size={0.7} /></span> >4
<Icon path={mdiStar} size={0.7} /></span
>
pity pity
</p> </p>
<p class="text-gray-400"> <p class="text-gray-400">
When the When the
<span class="inline-flex items-center">4 <span class="inline-flex items-center"
<Icon path={mdiStar} size={0.7} /></span> >4
<Icon path={mdiStar} size={0.7} /></span
>
pity reach 10, it will automatically reset to 0 pity reach 10, it will automatically reset to 0
</p> </p>
<p class="text-gray-400"> <p class="text-gray-400">
When the When the
<span class="inline-flex items-center">5 <span class="inline-flex items-center"
<Icon path={mdiStar} size={0.7} /></span> >5
<Icon path={mdiStar} size={0.7} /></span
>
pity reach 90, it will automatically reset to 0 pity reach 90, it will automatically reset to 0
</p> </p>
</div> </div>
@ -56,15 +74,28 @@
For when you do 10 pulls Wish, press the For when you do 10 pulls Wish, press the
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center">+10</b> <b class="rounded-lg px-2 py-1 border-white border inline-flex items-center">+10</b>
button, button,
<span class="text-gray-400">but the pity counter won't be accurate, because there is no way to tell when the drop <span class="text-gray-400"
occur (maybe you got it on the 1st or even the 10th). To make the counter still accurate, you need to check it on >but the pity counter won't be accurate, because there is no way to tell when the drop occur (maybe you got it on
the history table and add it 1 by 1 like you do 1 pull Wish.</span> the 1st or even the 10th). To make the counter still accurate, you need to check it on the history table and add
it 1 by 1 like you do 1 pull Wish.</span
>
</div> </div>
<div class="text-white p-2 bg-background rounded-xl mt-4"> <div class="text-white p-2 bg-background rounded-xl mt-4">
You can also press You can also press
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center"><Icon <b class="rounded-lg px-2 py-1 border-white border inline-flex items-center"><Icon path={mdiPencil} size={0.7} /></b
path={mdiPencil} >
size={0.7} /></b>
button to edit the values manually! button to edit the values manually!
</div> </div>
<div class="text-white p-2 bg-background rounded-xl mt-4">
Press the arrow on the bottom to see your pulls detail. A popup will show when you get <span
class="inline-flex items-center"
>5
<Icon path={mdiStar} size={0.7} /></span
>
or
<span class="inline-flex items-center"
>4
<Icon path={mdiStar} size={0.7} /></span
>. Or you can add or edit the table manually.
</div>
</div> </div>

View File

@ -1,21 +1,31 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount, getContext } from 'svelte';
import { mdiPencil, mdiStar } from '@mdi/js'; import { slide } from 'svelte/transition';
import { mdiPencil, mdiStar, mdiChevronDown } from '@mdi/js';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
const { open: openModal, close: closeModal } = getContext('simple-modal');
import Button from '../../components/Button.svelte'; import Button from '../../components/Button.svelte';
import Icon from '../../components/Icon.svelte'; import Icon from '../../components/Icon.svelte';
import Input from '../../components/Input.svelte'; import Input from '../../components/Input.svelte';
import AddModal from '../../components/WishCounterAddModal.svelte';
import { readSave, updateSave, fromRemote } from '../../stores/saveManager'; import { readSave, updateSave, fromRemote } from '../../stores/saveManager';
import { characters } from '../../data/characters';
import dayjs from 'dayjs';
import { weaponList } from '../../data/weaponList';
export let id = ''; export let id = '';
export let name = ''; export let name = '';
let isEdit = false; let isEdit = false;
let isDetailOpen = false;
let total = 0; let total = 0;
let legendary = 0; let legendary = 0;
let rare = 0; let rare = 0;
let pulls = [];
let totalEdit = 0; let totalEdit = 0;
let legendaryEdit = 0; let legendaryEdit = 0;
@ -25,11 +35,76 @@
$: if ($fromRemote) { $: if ($fromRemote) {
readLocalData(); readLocalData();
} }
$: sortedPull = pulls.sort((a, b) => b.time - a.time);
onMount(() => { onMount(() => {
readLocalData(); readLocalData();
}); });
function toggleDetail() {
isDetailOpen = !isDetailOpen;
}
function openAddModal(pity) {
openModal(
AddModal,
{
pity,
skip: closeModal,
addPullDetail,
},
{
closeButton: false,
closeOnOuterClick: false,
styleWindow: { background: '#25294A', width: '400px' },
},
);
}
function openEditModal(index, type, name, time, pity) {
openModal(
AddModal,
{
isEdit: true,
editType: type,
editName: name,
editTime: time,
pity,
skip: closeModal,
editPullDetail: (pull) => editPullDetail(index, pull),
deletePullDetail: () => deletePullDetail(index),
},
{
closeButton: false,
closeOnOuterClick: false,
styleWindow: { background: '#25294A', width: '400px' },
},
);
}
function addPullDetail(newPull) {
pulls = [...pulls, newPull];
closeModal();
saveData();
}
function editPullDetail(index, updatePull) {
const updated = sortedPull;
updated[index] = updatePull;
pulls = updated;
closeModal();
saveData();
}
function deletePullDetail(index) {
sortedPull.splice(index, 1);
pulls = sortedPull;
closeModal();
saveData();
}
function toggleEdit() { function toggleEdit() {
isEdit = !isEdit; isEdit = !isEdit;
if (isEdit) { if (isEdit) {
@ -56,6 +131,7 @@
total = counterData.total; total = counterData.total;
legendary = counterData.legendary; legendary = counterData.legendary;
rare = counterData.rare; rare = counterData.rare;
pulls = counterData.pulls || [];
} }
} }
@ -64,6 +140,7 @@
total, total,
legendary, legendary,
rare, rare,
pulls,
}); });
updateSave(path, data); updateSave(path, data);
@ -76,6 +153,7 @@
rare += val; rare += val;
if (rare >= 10) { if (rare >= 10) {
openAddModal(rare);
rare = 0; rare = 0;
} else if (rare < 0) { } else if (rare < 0) {
rare = 9; rare = 9;
@ -83,6 +161,7 @@
legendary += val; legendary += val;
if (legendary >= 90) { if (legendary >= 90) {
openAddModal(legendary);
legendary = 0; legendary = 0;
rare = 0; rare = 0;
} else if (legendary < 0) { } else if (legendary < 0) {
@ -93,6 +172,8 @@
} }
function getLegendary() { function getLegendary() {
openAddModal(legendary);
total += 1; total += 1;
legendary = 0; legendary = 0;
rare = 0; rare = 0;
@ -100,6 +181,8 @@
} }
function getRare() { function getRare() {
openAddModal(rare);
total += 1; total += 1;
legendary += 1; legendary += 1;
rare = 0; rare = 0;
@ -116,14 +199,20 @@
</div> </div>
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
<div <div
class={`${isEdit ? 'bg-item flex-col py-2' : 'bg-background flex-row items-center justify-center mb-2 p-4'} rounded-xl flex`}> class={`${
isEdit ? 'bg-item flex-col py-2' : 'bg-background flex-row items-center justify-center mb-2 p-4'
} rounded-xl flex`}
>
<span class="text-gray-200 whitespace-no-wrap flex-1">Lifetime Pulls</span> <span class="text-gray-200 whitespace-no-wrap flex-1">Lifetime Pulls</span>
{#if isEdit} {#if isEdit}
<Input type="number" min={1} bind:value={totalEdit} /> <Input type="number" min={1} bind:value={totalEdit} />
{:else}<span class="font-black text-3xl text-white ml-4">{total}</span>{/if} {:else}<span class="font-black text-3xl text-white ml-4">{total}</span>{/if}
</div> </div>
<div <div
class={`${isEdit ? 'bg-item flex-col py-2' : 'bg-background flex-row items-center justify-center mb-2 p-4'} rounded-xl flex`}> class={`${
isEdit ? 'bg-item flex-col py-2' : 'bg-background flex-row items-center justify-center mb-2 p-4'
} rounded-xl flex`}
>
<span class="text-gray-200 whitespace-no-wrap flex-1"> <span class="text-gray-200 whitespace-no-wrap flex-1">
5 5
<Icon path={mdiStar} size={0.75} className="mb-1" /> <Icon path={mdiStar} size={0.75} className="mb-1" />
@ -135,7 +224,10 @@
{:else}<span class="font-black text-3xl text-legendary-from ml-4">{legendary}</span>{/if} {:else}<span class="font-black text-3xl text-legendary-from ml-4">{legendary}</span>{/if}
</div> </div>
<div <div
class={`${isEdit ? 'bg-item flex-col py-2' : 'bg-background flex-row items-center justify-center mb-2 p-4'} rounded-xl flex`}> class={`${
isEdit ? 'bg-item flex-col py-2' : 'bg-background flex-row items-center justify-center mb-2 p-4'
} rounded-xl flex`}
>
<span class="text-gray-200 whitespace-no-wrap flex-1"> <span class="text-gray-200 whitespace-no-wrap flex-1">
4 4
<Icon path={mdiStar} size={0.75} className="mb-1" /> <Icon path={mdiStar} size={0.75} className="mb-1" />
@ -166,4 +258,47 @@
</div> </div>
{/if} {/if}
</div> </div>
{#if isDetailOpen}
<div transition:slide class="mt-4 text-white">
<table class="w-full">
<tr>
<th class="border-b border-gray-700 text-left pl-2">Name</th>
<th class="border-b border-gray-700 text-left pl-2">Time</th>
<th class="border-b border-gray-700 text-center">Pity</th>
</tr>
{#each sortedPull as pull, index}
<tr on:click={() => openEditModal(index, pull.type, pull.id, pull.time, pull.pity)}>
{#if pull.type === 'character'}
<td
class={`border-b border-gray-700 py-1 pl-2 font-semibold ${
characters[pull.id].rarity === 5 ? 'text-legendary-from' : 'text-rare-from'
}`}>{characters[pull.id].name}</td
>
{:else}
<td
class={`border-b border-gray-700 py-1 pl-2 font-semibold ${
weaponList[pull.id].rarity === 5 ? 'text-legendary-from' : 'text-rare-from'
}`}>{weaponList[pull.id].name}</td
>
{/if}
<td class="border-b border-gray-700 py-1 px-2">{dayjs.unix(pull.time).format('YYYY-MM-DD HH:mm')}</td>
<td class="text-center border-b border-gray-700 py-1">{pull.pity}</td>
</tr>
{/each}
</table>
<div class="mt-4 flex justify-end">
<div class="bg-background rounded-xl px-4 mr-2 flex items-center">
<span>Click the list to edit or delete</span>
</div>
<Button size="sm" className="w-16" on:click={() => openAddModal(0)}>Add</Button>
</div>
</div>
{/if}
<div class="flex justify-center items-end h-8 mt-2" on:click={toggleDetail}>
<Icon
path={mdiChevronDown}
color="white"
className={`duration-100 ease-in ${isDetailOpen ? 'transform rotate-180' : ''}`}
/>
</div>
</div> </div>

View File

@ -2,7 +2,7 @@ import dayjs from 'dayjs';
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import { synced, saveId, localModified, lastSyncTime } from './dataSync'; import { synced, saveId, localModified, lastSyncTime, driveSignedIn } from './dataSync';
import { pushToast } from './toast'; import { pushToast } from './toast';
export const updateTime = writable(null); export const updateTime = writable(null);
@ -13,11 +13,16 @@ export const UPDATE_TIME_KEY = 'update-time';
let pendingQueue = []; let pendingQueue = [];
let queueSave = true; let queueSave = true;
let saveFileId = ''; let saveFileId = '';
let signedIn = false;
saveId.subscribe((val) => { saveId.subscribe((val) => {
saveFileId = val; saveFileId = val;
}); });
driveSignedIn.subscribe((val) => {
signedIn = val;
});
const saveToRemote = debounce(() => { const saveToRemote = debounce(() => {
saveData(getLocalSaveJson()); saveData(getLocalSaveJson());
}, 5000); }, 5000);
@ -38,10 +43,10 @@ async function saveData(data) {
synced.set(true); synced.set(true);
localModified.set(false); localModified.set(false);
pushToast('Data has been synced!') pushToast('Data has been synced!');
} catch (err) { } catch (err) {
console.error(err); console.error(err);
pushToast('Error when uploading your data!', 'error') pushToast('Error when uploading your data!', 'error');
synced.set(true); synced.set(true);
} }
} }
@ -81,10 +86,13 @@ export const updateSave = (key, data, isFromRemote) => {
localStorage.setItem(key, data); localStorage.setItem(key, data);
if (!isFromRemote) { if (!isFromRemote) {
const currentTime = dayjs().toISOString(); const currentTime = dayjs();
updateTime.set(currentTime); updateTime.set(currentTime);
localStorage.setItem(UPDATE_TIME_KEY, currentTime); localStorage.setItem(UPDATE_TIME_KEY, currentTime.toISOString());
saveToRemote();
if (signedIn) {
saveToRemote();
}
} else { } else {
fromRemote.set(true); fromRemote.set(true);
} }