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();
export let className;
export let className = '';
export let icon = null;
export let options;
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
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center">+1</b>
when you get
<span class="inline-flex items-center">3
<Icon path={mdiStar} size={0.7} /></span>
<span class="inline-flex items-center"
>3
<Icon path={mdiStar} size={0.7} /></span
>
</p>
<p class="mb-2">
Press
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center">Get 4
<Icon path={mdiStar} size={0.7} /></b>
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center"
>Get 4
<Icon path={mdiStar} size={0.7} /></b
>
when you get
<span class="inline-flex items-center">4
<Icon path={mdiStar} size={0.7} /></span>
<span class="inline-flex items-center"
>4
<Icon path={mdiStar} size={0.7} /></span
>
</p>
<p class="mb-2">
Press
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center">Get 5
<Icon path={mdiStar} size={0.7} /></b>
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center"
>Get 5
<Icon path={mdiStar} size={0.7} /></b
>
when you get
<span class="inline-flex items-center">5
<Icon path={mdiStar} size={0.7} /></span>
<span class="inline-flex items-center"
>5
<Icon path={mdiStar} size={0.7} /></span
>
</p>
<p class="text-gray-400">
It will automatically add the lifetime pulls,
<span class="inline-flex items-center">5
<Icon path={mdiStar} size={0.7} /></span>
<span class="inline-flex items-center"
>5
<Icon path={mdiStar} size={0.7} /></span
>
and
<span class="inline-flex items-center">4
<Icon path={mdiStar} size={0.7} /></span>
<span class="inline-flex items-center"
>4
<Icon path={mdiStar} size={0.7} /></span
>
pity
</p>
<p class="text-gray-400">
When the
<span class="inline-flex items-center">4
<Icon path={mdiStar} size={0.7} /></span>
<span class="inline-flex items-center"
>4
<Icon path={mdiStar} size={0.7} /></span
>
pity reach 10, it will automatically reset to 0
</p>
<p class="text-gray-400">
When the
<span class="inline-flex items-center">5
<Icon path={mdiStar} size={0.7} /></span>
<span class="inline-flex items-center"
>5
<Icon path={mdiStar} size={0.7} /></span
>
pity reach 90, it will automatically reset to 0
</p>
</div>
@ -56,15 +74,28 @@
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>
button,
<span class="text-gray-400">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 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>
<span class="text-gray-400"
>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 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 class="text-white p-2 bg-background rounded-xl mt-4">
You can also press
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center"><Icon
path={mdiPencil}
size={0.7} /></b>
<b class="rounded-lg px-2 py-1 border-white border inline-flex items-center"><Icon path={mdiPencil} size={0.7} /></b
>
button to edit the values manually!
</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>

View File

@ -1,21 +1,31 @@
<script>
import { onMount } from 'svelte';
import { mdiPencil, mdiStar } from '@mdi/js';
import { onMount, getContext } from 'svelte';
import { slide } from 'svelte/transition';
import { mdiPencil, mdiStar, mdiChevronDown } from '@mdi/js';
import debounce from 'lodash/debounce';
const { open: openModal, close: closeModal } = getContext('simple-modal');
import Button from '../../components/Button.svelte';
import Icon from '../../components/Icon.svelte';
import Input from '../../components/Input.svelte';
import AddModal from '../../components/WishCounterAddModal.svelte';
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 name = '';
let isEdit = false;
let isDetailOpen = false;
let total = 0;
let legendary = 0;
let rare = 0;
let pulls = [];
let totalEdit = 0;
let legendaryEdit = 0;
@ -25,11 +35,76 @@
$: if ($fromRemote) {
readLocalData();
}
$: sortedPull = pulls.sort((a, b) => b.time - a.time);
onMount(() => {
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() {
isEdit = !isEdit;
if (isEdit) {
@ -56,6 +131,7 @@
total = counterData.total;
legendary = counterData.legendary;
rare = counterData.rare;
pulls = counterData.pulls || [];
}
}
@ -64,6 +140,7 @@
total,
legendary,
rare,
pulls,
});
updateSave(path, data);
@ -76,6 +153,7 @@
rare += val;
if (rare >= 10) {
openAddModal(rare);
rare = 0;
} else if (rare < 0) {
rare = 9;
@ -83,6 +161,7 @@
legendary += val;
if (legendary >= 90) {
openAddModal(legendary);
legendary = 0;
rare = 0;
} else if (legendary < 0) {
@ -93,6 +172,8 @@
}
function getLegendary() {
openAddModal(legendary);
total += 1;
legendary = 0;
rare = 0;
@ -100,6 +181,8 @@
}
function getRare() {
openAddModal(rare);
total += 1;
legendary += 1;
rare = 0;
@ -116,14 +199,20 @@
</div>
<div class="flex flex-col w-full">
<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>
{#if isEdit}
<Input type="number" min={1} bind:value={totalEdit} />
{:else}<span class="font-black text-3xl text-white ml-4">{total}</span>{/if}
</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">
5
<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}
</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">
4
<Icon path={mdiStar} size={0.75} className="mb-1" />
@ -166,4 +258,47 @@
</div>
{/if}
</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>

View File

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