this is so cracked lol

This commit is contained in:
a 2022-07-03 05:25:12 -05:00
parent b3dad219c6
commit 080215183f
24 changed files with 1114 additions and 273 deletions

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<body style="overflow-y: hidden;">
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>

100
package-lock.json generated
View File

@ -14,6 +14,8 @@
"@vueuse/core": "^8.7.5",
"axios": "^0.27.2",
"handsontable": "^12.0.1",
"loglevel": "^1.8.0",
"pinia": "^2.0.14",
"qs": "^6.10.5",
"typescript-cookie": "^1.0.3",
"vue": "^3.2.25",
@ -173,6 +175,11 @@
"@vue/shared": "3.2.37"
}
},
"node_modules/@vue/devtools-api": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.0.tgz",
"integrity": "sha512-pF1G4wky+hkifDiZSWn8xfuLOJI1ZXtuambpBEYaf7Xaf6zC/pM29rvAGpd3qaGXnr4BAXU1Pxz/VfvBGwexGA=="
},
"node_modules/@vue/reactivity": {
"version": "3.2.37",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.37.tgz",
@ -882,6 +889,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/loglevel": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
"integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==",
"engines": {
"node": ">= 0.6.0"
},
"funding": {
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/loglevel"
}
},
"node_modules/magic-string": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
@ -963,6 +982,56 @@
"resolved": "https://registry.npmjs.org/pikaday/-/pikaday-1.8.0.tgz",
"integrity": "sha512-SgGxMYX0NHj9oQnMaSyAipr2gOrbB4Lfs/TJTb6H6hRHs39/5c5VZi73Q8hr53+vWjdn6HzkWcj8Vtl3c9ziaA=="
},
"node_modules/pinia": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz",
"integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==",
"dependencies": {
"@vue/devtools-api": "^6.1.4",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"@vue/composition-api": "^1.4.0",
"typescript": ">=4.4.4",
"vue": "^2.6.14 || ^3.2.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"typescript": {
"optional": true
}
}
},
"node_modules/pinia/node_modules/vue-demi": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.1.tgz",
"integrity": "sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/postcss": {
"version": "8.4.14",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
@ -1100,7 +1169,7 @@
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
"dev": true,
"devOptional": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -1331,6 +1400,11 @@
"@vue/shared": "3.2.37"
}
},
"@vue/devtools-api": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.2.0.tgz",
"integrity": "sha512-pF1G4wky+hkifDiZSWn8xfuLOJI1ZXtuambpBEYaf7Xaf6zC/pM29rvAGpd3qaGXnr4BAXU1Pxz/VfvBGwexGA=="
},
"@vue/reactivity": {
"version": "3.2.37",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.37.tgz",
@ -1740,6 +1814,11 @@
"has": "^1.0.3"
}
},
"loglevel": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
"integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA=="
},
"magic-string": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
@ -1800,6 +1879,23 @@
"resolved": "https://registry.npmjs.org/pikaday/-/pikaday-1.8.0.tgz",
"integrity": "sha512-SgGxMYX0NHj9oQnMaSyAipr2gOrbB4Lfs/TJTb6H6hRHs39/5c5VZi73Q8hr53+vWjdn6HzkWcj8Vtl3c9ziaA=="
},
"pinia": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.14.tgz",
"integrity": "sha512-0nPuZR4TetT/WcLN+feMSjWJku3SQU7dBbXC6uw+R6FLQJCsg+/0pzXyD82T1FmAYe0lsx+jnEDQ1BLgkRKlxA==",
"requires": {
"@vue/devtools-api": "^6.1.4",
"vue-demi": "*"
},
"dependencies": {
"vue-demi": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.1.tgz",
"integrity": "sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg==",
"requires": {}
}
}
},
"postcss": {
"version": "8.4.14",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
@ -1891,7 +1987,7 @@
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
"dev": true
"devOptional": true
},
"typescript-cookie": {
"version": "1.0.3",

View File

@ -14,6 +14,8 @@
"@vueuse/core": "^8.7.5",
"axios": "^0.27.2",
"handsontable": "^12.0.1",
"loglevel": "^1.8.0",
"pinia": "^2.0.14",
"qs": "^6.10.5",
"typescript-cookie": "^1.0.3",
"vue": "^3.2.25",

View File

@ -1,13 +1,25 @@
<script setup lang="ts">
import CharacterInventory from "./components/CharacterInventory.vue"
import Login from "./pages/login.vue"
import SessionDisplay from "./components/SessionDisplay.vue";
import CharacterRoulette from "./components/CharacterRoulette.vue";
import Sidebar from "./components/Sidebar.vue";
</script>
<template>
<SessionDisplay/>
<Login/>
<CharacterInventory/>
<div class="parent">
<div class="splash"> </div>
<div class="main">
<CharacterInventory />
</div>
<div class="sidebar">
<Sidebar/>
</div>
<div class="select">
<CharacterRoulette />
</div>
<div class="login">
<Login />
</div>
</div>
</template>
<style>
@ -18,6 +30,8 @@ import SessionDisplay from "./components/SessionDisplay.vue";
text-align: center;
color: #2c3e50;
margin-top: 60px;
height: 100vh;
overflow-y: hidden;
}
.handsontable td {
@ -27,7 +41,41 @@ import SessionDisplay from "./components/SessionDisplay.vue";
border-bottom: 1px white !important;
background-color: #F7F7F7 !important;
}
.handsontable tr {
border-radius: 10px !important;
}
</style>
<style>
.parent {
display: grid;
grid-template-columns: 1fr 4fr 3fr;
grid-template-rows: 1fr repeat(2, 3fr) 1fr;
grid-column-gap: 0px;
grid-row-gap: 0px;
overflow: hidden;
}
.splash {
grid-area: 1 / 1 / 2 / 2;
}
.main {
grid-area: 2 / 2 / 5 / 4;
overflow-x: scroll;
overflow-y: scroll;
}
.sidebar {
grid-area: 2 / 1 / 5 / 2;
}
.selection {
grid-area: 1 / 2 / 2 / 3;
}
.login {
grid-area: 1 / 3 / 2 / 4;
}
</style>

35
src/ColumnCheckbox.vue Normal file
View File

@ -0,0 +1,35 @@
<template>
<input type="checkbox" id={{props.colname}} v-model="checked" />
<label for={{props.colname}}>{{(props.label ? props.label : Columns[props.colname].displayName)}}</label>
</template>
<script lang="ts" setup>
const props = defineProps(["colname","label"])
const {columns} = useStoreRef()
const checked = ref(columns.value.has(props.colname))
watch(columns.value.dirty,()=>{
console.log("changed")
if(columns.value.has(props.colname)) {
checked.value = true
}else{
checked.value = false
}
},{deep:true})
watch(checked, ()=>{
if(checked.value === true) {
columns.value.add(props.colname)
return
}
if(checked.value === false) {
columns.value.delete(props.colname)
return
}
})
</script>
<script lang="ts">
import { defineProps, ref, watch } from 'vue';
import { useStoreRef } from '../state/state';
import { ColumnName, Columns } from '../lib/columns';
</script>

View File

@ -0,0 +1,37 @@
<template>
<div>
<div
v-on:click="selectCharacter()"
>{{name}} the <span v-html="job" /> ({{galders.toLocaleString()}}g)</div>
</div>
</template>
<script lang="ts" setup>
const session = storage.GetSession()
const api:LTOApi = new LTOApiv0(session)
const props = defineProps(['character'])
const name = ref("")
const job = ref("")
const galders = ref(0)
const {invs, activeTable} = useStoreRef()
name.value = invs.value.get(props.character)?.name!
job.value = invs.value.get(props.character)?.wallet?.job_img!
galders.value = invs.value.get(props.character)?.wallet?.galders!
const selectCharacter = () => {
activeTable.value = props.character
log.info("selected char", activeTable.value)
}
</script>
<script lang="ts">
import log from 'loglevel';
import { defineComponent, computed, PropType, defineProps, defineEmits, ref} from 'vue';
import { LTOApi, LTOApiv0 } from '../lib/lifeto';
import { LoginHelper, Session } from '../lib/session';
import { storage } from '../session_storage';
import { useStore, useStoreRef } from '../state/state';
</script>

View File

@ -1,62 +1,51 @@
<template>
<input v-on:input="swapHotData" placeholder="separate by comma" value="Image, Name, Count, MoveCount, Move, MoveConfirm">
<hot-table
<HotTable
ref="hotTableComponent"
:settings="hotSettings"
></hot-table>
:settings="DefaultSettings()"
></HotTable>
</template>
<script lang="ts">
import { defineComponent, computed, PropType, defineProps, defineEmits} from 'vue';
import { HotTable, HotColumn} from '@handsontable/vue3';
import { registerAllModules } from 'handsontable/registry';
import { InventoryTable, TableRecipe } from '../lib/table';
import { Columns, ColumnByNames } from '../lib/columns';
import { TricksterItem, SampleData } from '../lib/trickster';
import Handsontable from 'handsontable';
<script lang="ts" setup>
import { ref } from 'vue';
import { HotTable, HotColumn } from '@handsontable/vue3';
const session = storage.GetSession()
const api:LTOApi = new LTOApiv0(session)
const {invs, activeTable, columns, tags} = useStoreRef()
const hotTableComponent = ref<any>(null)
const updateTable = () => {
if (invs.value.has(activeTable.value)) {
const chardat = invs.value.get(activeTable.value)
if (chardat) {
const it = new InventoryTable(chardat!, { columns: columns.value, tags: tags.value })
const hot = (hotTableComponent.value.hotInstance as Handsontable)
const build = it.BuildTable()
hot.updateSettings(build.settings)
hot.updateData(build.data)
}
}
}
// register Handsontable's modules
registerAllModules();
const _defaultColumn = [
Columns.Image,
Columns.Name,
Columns.Count,
Columns.MoveCount,
Columns.Move,
]
watch([columns.value.dirty,tags.value.dirty, activeTable], () => {
updateTable()
})
export default defineComponent({
data() {
let cols = _defaultColumn
const it = new InventoryTable(SampleData.aysheBoyfriend,
...cols
);
const dat = it.BuildTable()
return {
hotSettings: {
data: dat.data,
...dat.settings,
}
};
},
methods: {
swapHotData: function(event:any) {
let trm = event.target.value.split(",").map((x:any)=>x.trim())
let cols = ColumnByNames(...(trm as any)).filter(x=>x!=undefined)
if(cols.length < 2) {
cols = _defaultColumn
}
const it = new InventoryTable(SampleData.aysheBoyfriend,
...cols)
const hot = ((this.$refs!.hotTableComponent as any).hotInstance as Handsontable)
hot.updateSettings(it.BuildTable().settings)
}
},
components: {
HotTable,
}
});
</script>
<style src="handsontable/dist/handsontable.full.css"></style>
<script lang="ts">
import { defineComponent, computed, PropType, defineProps, defineEmits, watch} from 'vue';
import { registerAllModules } from 'handsontable/registry';
import { DefaultSettings, InventoryTable, TableRecipe } from '../lib/table';
import { Columns, ColumnByNames, ColumnInfo } from '../lib/columns';
import { TricksterItem, SampleData } from '../lib/trickster';
import Handsontable from 'handsontable';
import { useStoreRef } from '../state/state';
import { storage } from '../session_storage';
import { LTOApi, LTOApiv0 } from '../lib/lifeto';
</script>
<style src="handsontable/dist/handsontable.full.css">
</style>

View File

@ -0,0 +1,42 @@
<template>
<div v-for="v in characters">
<CharacterCard :character="v" />
</div>
</template>
<script lang="ts" setup>
import CharacterCard from './CharacterCard.vue';
const { accounts, invs } = useStoreRef()
const characters = ref([] as string[])
watch(invs, () => {
characters.value = [...new Set([...characters.value, ...invs.value.keys()])]
}, { deep: true })
const session = storage.GetSession()
const api: LTOApi = new LTOApiv0(session)
api.GetAccounts().then(xs => {
xs.forEach(x => {
accounts.value.add(x)
api.GetCharacters(x).then(chars => {
chars.forEach(char => {
log.debug("new character", char)
invs.value.set(char.path, char)
})
})
})
})
</script>
<script lang="ts">
import { defineComponent, computed, PropType, defineProps, defineEmits, ref, watch } from 'vue';
import { LTOApi, LTOApiv0 } from '../lib/lifeto';
import { LoginHelper, Session } from '../lib/session';
import { storage } from '../session_storage';
import { useStore, useStoreRef } from '../state/state';
import log from 'loglevel';
</script>

View File

@ -0,0 +1,35 @@
<template>
<input type="checkbox" id={{props.colname}} v-model="checked" />
<label for={{props.colname}}>{{(props.label ? props.label : Columns[props.colname].displayName)}}</label>
</template>
<script lang="ts" setup>
const props = defineProps(["colname","label"])
const {columns} = useStoreRef()
const checked = ref(columns.value.has(props.colname))
watch(columns.value.dirty,()=>{
console.log("changed")
if(columns.value.has(props.colname)) {
checked.value = true
}else{
checked.value = false
}
},{deep:true})
watch(checked, ()=>{
if(checked.value === true) {
columns.value.add(props.colname)
return
}
if(checked.value === false) {
columns.value.delete(props.colname)
return
}
})
</script>
<script lang="ts">
import { defineProps, ref, watch } from 'vue';
import { useStoreRef } from '../state/state';
import { ColumnName, Columns } from '../lib/columns';
</script>

View File

@ -0,0 +1,124 @@
<template>
<input
type="checkbox"
class="css-checkbox"
:id="'toggle-'+props.header"
v-model="show"
/>
<label :for="'toggle-'+props.header" class="css-label">
<span class="fa fa-plus">+</span>
<span class="fa fa-minus">-</span>
</label>
<label :for="'checkbox-'+props.header">{{props.header}}</label>
<input type="checkbox" :id="'checkbox-'+props.header" v-model="checked" />
<br>
<div
class="checkbox_parent"
:style="'grid-template-rows: repeat('+Math.ceil(props.columns.length/2+2)+', 1fr);'"
v-if="show"
>
<div
v-for="(item, index) in props.columns"
class="checkbox_child"
>
<ColumnCheckbox :colname="item"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import ColumnCheckbox from './ColumnCheckbox.vue';
const props = defineProps<{
header: string
columns: ColumnName[]
default?: boolean
}>()
const {columns} = useStoreRef()
const checked = ref(props.default)
const show = ref(true)
watch(show,()=>{
})
watch(checked,()=>{
if(checked.value === true) {
props.columns.forEach(x=>columns.value.add(x))
return
}
if(checked.value === false) {
props.columns.forEach(x=>columns.value.delete(x))
return
}
})
</script>
<script lang="ts">
import { defineProps, ref, watch } from 'vue';
import { useStoreRef } from '../state/state';
import { ColumnName } from '../lib/columns';
</script>
<style>
.checkbox_parent {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-column-gap: 0px;
grid-row-gap: 0px;
}
.checkbox_child {
align-content: left;
justify-self: left;
}
.css-label {
cursor: pointer;
}
.css-checkbox {
display: none;
}
.fa {
color: white;
border-radius: 4px;
padding-top: 0px;
padding-right: 4px;
padding-left: 4px;
padding-bottom: 0px;
}
.fa-plus {
background-color: #E85764;
}
.fa-minus {
background-color: #3AC5C9;
display: none;
}
.css-checkbox:checked + .css-label .fa-minus {
display: inline;
}
.css-checkbox:checked + .css-label .fa-plus {
display: none;
}
</style>

View File

@ -0,0 +1,35 @@
<template>
<input type="checkbox" id={{props.colname}} v-model="checked" />
<label for={{props.colname}}>{{(props.label ? props.label : Columns[props.colname].displayName)}}</label>
</template>
<script lang="ts" setup>
const props = defineProps(["colname","label"])
const {tags} = useStoreRef()
const checked = ref(tags.value.has(props.colname))
watch(tags.value.dirty,()=>{
console.log("changed")
if(tags.value.has(props.colname)) {
checked.value = true
}else{
checked.value = false
}
},{deep:true})
watch(checked, ()=>{
if(checked.value === true) {
tags.value.add(props.colname)
return
}
if(checked.value === false) {
tags.value.delete(props.colname)
return
}
})
</script>
<script lang="ts">
import { defineProps, ref, watch } from 'vue';
import { useStoreRef } from '../state/state';
import { ColumnName, Columns } from '../lib/columns';
</script>

View File

@ -0,0 +1,123 @@
<template>
<input
type="checkbox"
class="css-checkbox"
:id="'toggle-'+props.header"
v-model="show"
/>
<label :for="'toggle-'+props.header" class="css-label">
<span class="fa fa-plus">+</span>
<span class="fa fa-minus">-</span>
</label>
<label :for="'checkbox-'+props.header">{{props.header}}</label>
<input type="checkbox" :id="'checkbox-'+props.header" v-model="checked" />
<br>
<div
class="checkbox_parent"
:style="'grid-template-rows: repeat('+Math.ceil(props.columns.length/2+2)+', 1fr);'"
v-if="show"
>
<div
v-for="(item, index) in props.columns"
class="checkbox_child"
>
<FilterCheckbox :colname="item"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import FilterCheckbox from './FilterCheckbox.vue';
const props = defineProps<{
header: string
columns: ColumnName[]
}>()
const {tags} = useStoreRef()
const checked = ref(false)
const show = ref(true)
watch(show,()=>{
})
watch(checked,()=>{
if(checked.value === true) {
props.columns.forEach(x=>tags.value.add(x))
return
}
if(checked.value === false) {
props.columns.forEach(x=>tags.value.delete(x))
return
}
})
</script>
<script lang="ts">
import { defineProps, ref, watch } from 'vue';
import { useStoreRef } from '../state/state';
import { ColumnName } from '../lib/columns';
</script>
<style>
.checkbox_parent {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-column-gap: 0px;
grid-row-gap: 0px;
}
.checkbox_child {
align-content: left;
justify-self: left;
}
.css-label {
cursor: pointer;
}
.css-checkbox {
display: none;
}
.fa {
color: white;
border-radius: 4px;
padding-top: 0px;
padding-right: 4px;
padding-left: 4px;
padding-bottom: 0px;
}
.fa-plus {
background-color: #E85764;
}
.fa-minus {
background-color: #3AC5C9;
display: none;
}
.css-checkbox:checked + .css-label .fa-minus {
display: inline;
}
.css-checkbox:checked + .css-label .fa-plus {
display: none;
}
</style>

View File

@ -1,24 +0,0 @@
<template>
<button @click="refreshSessions">
Refresh
</button>
</template>
<script lang="ts">
import { defineComponent, computed, PropType, defineProps, defineEmits} from 'vue';
import { Session } from '../lib/session';
import { storage } from '../session_storage';
export default defineComponent({
data() {
return {
Sessions: {} as any,
};
},
methods: {
refreshSessions: function(event:any) {
this.Sessions = storage.GetSessions()
},
},
});
</script>

View File

@ -0,0 +1,28 @@
<template>
Filters:
<br>
<FilterCheckboxGroup :header="'tags:'" :columns="TagColumns" />
<br>
<br>
Columns:
<br>
<ColumnCheckboxGroup :header="'action:'" :columns="MoveColumns" :default="true" />
<ColumnCheckboxGroup :header="'details:'" :columns="DetailsColumns" :default="true"/>
<ColumnCheckboxGroup :header="'equipment:'" :columns="EquipmentColumns" />
<ColumnCheckboxGroup :header="'stats:'" :columns="StatsColumns" />
</template>
<script lang="ts" setup>
import ColumnCheckboxGroup from './ColumnCheckboxGroup.vue';
import FilterCheckboxGroup from './FilterCheckboxGroup.vue';
import { StatsColumns, MoveColumns, TagColumns, EquipmentColumns, DetailsColumns } from '../lib/columns';
const { accounts, invs } = useStoreRef()
</script>
<script lang="ts">
import { useStoreRef } from '../state/state';
</script>

View File

@ -5,13 +5,62 @@ import { TricksterInventory, TricksterItem } from "./trickster"
import Core from "handsontable/core";
type DefaultColumnName = "Image"|"Name"|"Count"
type ActionColumnName = "Move"|"MoveCount"|"ConfirmMove"
type TagColumName = "Equip"|"Drill"|"Card"|"Quest"|"Consume"
type StatColumnName = "AP"|"Gun AP"|"AC"|"DX"|"MP"|"MA"|"MD"|"WT"|"DA"|"LK"|"HP"|"DP"|"HV"
type EquipmentColumnName = "MinLvl"|"Slots"|"RefineNumber"|"RefineState"
type ColumnName = DefaultColumnName | TagColumName | StatColumnName | ActionColumnName | EquipmentColumnName
export const BasicColumns = [
"Image","Name","Count",
]
export const DetailsColumns = [
"Desc","Use",
]
export const MoveColumns = [
"Move","MoveCount",
]
export const TagColumns = [
"Equip","Drill","Card","Quest","Consume"
]
export const HackColumns = [
"All"
]
export const EquipmentColumns = [
"MinLvl","Slots","RefineNumber","RefineState",
]
export const StatsColumns = [
"AP","GunAP","AC","DX","MP","MA","MD","WT","DA","LK","HP","DP","HV",
]
export const ColumnNames = [
...BasicColumns,
...MoveColumns,
...DetailsColumns,
...EquipmentColumns,
...StatsColumns,
...TagColumns,
]
export type ColumnName = typeof ColumnNames[number]
const c = (a:ColumnName | ColumnInfo):ColumnName => {
switch(typeof a) {
case "string":
return a
case "object":
return a.name
}
}
export const LazyColumn = c;
export const ColumnSorter = (a:ColumnName | ColumnInfo, b: ColumnName | ColumnInfo):number => {
let n1 = ColumnNames.indexOf(c(a))
let n2 = ColumnNames.indexOf(c(b))
if(n1 == n2) {
return 0
}
return n1 > n2 ? 1 : -1
}
export interface ColumnInfo {
name: ColumnName
@ -132,15 +181,6 @@ function moveCountRenderer(instance:Core, td:any, row:number, col:number, prop:a
}
class ConfirmMove implements ColumnInfo {
name:ColumnName = "ConfirmMove"
displayName = "Confirm"
writable = true
getter(item:TricksterItem):(string|number){
return 0
}
}
class Equip implements ColumnInfo {
name:ColumnName = "Equip"
displayName = "equip"
@ -157,6 +197,14 @@ class Drill implements ColumnInfo {
}
}
class All implements ColumnInfo {
name:ColumnName = "All"
displayName = "all"
getter(_:TricksterItem):(string|number){
return -10000
}
}
class Card implements ColumnInfo {
name:ColumnName = "Card"
displayName = "card"
@ -202,7 +250,7 @@ class AP implements ColumnInfo {
}
class GunAP implements ColumnInfo {
name:ColumnName = "Gun AP"
name:ColumnName = "GunAP"
displayName = "Gun AP"
getter(item:TricksterItem):(string|number){
return item.stats ? item.stats["Gun AP"] : ""
@ -301,7 +349,7 @@ class MinLvl implements ColumnInfo {
displayName = "lvl"
getter(item:TricksterItem):(string|number){
//TODO:
return 0
return item.item_min_level? item.item_min_level:""
}
}
@ -310,13 +358,13 @@ class Slots implements ColumnInfo {
displayName = "slots"
getter(item:TricksterItem):(string|number){
//TODO:
return 0
return item.item_slots ? item.item_slots : ""
}
}
class RefineNumber implements ColumnInfo {
name:ColumnName = "RefineNumber"
displayName = "R#"
displayName = "refine"
getter(item:TricksterItem):(string|number){
return item.refine_level ? item.refine_level : 0
}
@ -324,31 +372,84 @@ class RefineNumber implements ColumnInfo {
class RefineState implements ColumnInfo {
name:ColumnName = "RefineState"
displayName = "State"
displayName = "bork"
getter(item:TricksterItem):(string|number){
return item.refine_state ? item.refine_state : 0
}
}
class Desc implements ColumnInfo {
name:ColumnName = "Desc"
displayName = "desc"
renderer = descRenderer
getter(item:TricksterItem):(string|number){
return item.item_desc
}
}
function descRenderer(instance:any, td:any, row:any, col:any, prop:any, value:any, cellProperties:any) {
const stringifiedValue = Handsontable.helper.stringify(value);
let showText = stringifiedValue;
const div= document.createElement('div');
div.innerHTML = showText
div.title = showText
div.style.maxWidth = "30ch"
div.style.textOverflow = "ellipsis"
div.style.overflow= "hidden"
div.style.whiteSpace= "nowrap"
Handsontable.dom.addEvent(div, 'mousedown', event =>{
event!.preventDefault();
});
Handsontable.dom.empty(td);
td.appendChild(div);
td.classList.add("htLeft")
}
class Use implements ColumnInfo {
name:ColumnName = "Use"
displayName = "use"
renderer= useRenderer;
getter(item:TricksterItem):(string|number){
return item.item_use
}
}
function useRenderer(instance:any, td:any, row:any, col:any, prop:any, value:any, cellProperties:any) {
const stringifiedValue = Handsontable.helper.stringify(value);
let showText = stringifiedValue;
const div= document.createElement('div');
div.title = showText
div.innerHTML = showText
div.style.maxWidth = "30ch"
div.style.textOverflow = "ellipsis"
div.style.overflow= "hidden"
div.style.whiteSpace= "nowrap"
Handsontable.dom.addEvent(div, 'mousedown', event =>{
event!.preventDefault();
});
Handsontable.dom.empty(td);
td.appendChild(div);
td.classList.add("htLeft")
}
export const ColumnByNames = (...n:ColumnName[]) => {
return n.map(ColumnByName)
}
export const ColumnByName = (n:ColumnName) => {
return Columns[n]
}
export const Columns = {
export const Columns:{[Property in ColumnName]:ColumnInfo}= {
Use: new Use(),
Desc: new Desc(),
Image: new Image(),
Name: new Name(),
Count: new Count(),
Move: new Move(),
MoveCount: new MoveCount(),
ConfirmMove: new ConfirmMove(),
Equip: new Equip(),
Drill: new Drill(),
Card: new Card(),
@ -356,7 +457,6 @@ export const Columns = {
Consume: new Consume(),
AP: new AP(),
GunAP: new GunAP(),
'Gun AP': new GunAP(),
AC: new AC(),
DX: new DX(),
MP: new MP(),
@ -372,33 +472,5 @@ export const Columns = {
Slots: new Slots(),
RefineNumber: new RefineNumber(),
RefineState: new RefineState(),
image: new Image(),
name: new Name(),
count: new Count(),
move: new Move(),
movecount: new MoveCount(),
confirmmove: new ConfirmMove(),
equip: new Equip(),
drill: new Drill(),
card: new Card(),
quest: new Quest(),
consume: new Consume(),
ap: new AP(),
gunap: new GunAP(),
'gun ap': new GunAP(),
ac: new AC(),
dx: new DX(),
mp: new MP(),
ma: new MA(),
md: new MD(),
wt: new WT(),
da: new DA(),
lk: new LK(),
hp: new HP(),
dp: new DP(),
hv: new HV(),
minlvl: new MinLvl(),
slots: new Slots(),
refinenumber: new RefineNumber(),
refinestate: new RefineState(),
All: new All(),
}

105
src/lib/lifeto.ts Normal file
View File

@ -0,0 +1,105 @@
import { Axios, AxiosResponse } from "axios"
import log from "loglevel"
import { Session } from "./session"
import { TricksterInventory, TricksterItem, TricksterWallet } from "./trickster"
export interface LTOApi {
GetCharacters:(name:string)=>Promise<Array<TricksterInventory>>
GetAccounts:() =>Promise<Array<string>>
GetLoggedin: ()=>Promise<boolean>
}
export class LTOApiv0 implements LTOApi {
s: Session
constructor(s:Session) {
this.s = s
}
GetCharacters = async (account: string):Promise<Array<TricksterInventory>> =>{
return this.s.authed_request("GET", `item-manager/items/account/${account}`,undefined).then(async (ans:AxiosResponse)=>{
const o = ans.data
log.debug("GetCharacters", o)
let out = [{
name: account,
id: ":" + account,
path: account,
wallet:{
galders:0,
state:0,
job_img: "BANK",
} as TricksterWallet,
items:(Object.entries(o.items) as any).map(([k, v]: [string, TricksterItem]):TricksterItem=>{
v.unique_id = Number(k)
return v
}),
} as TricksterInventory]
await Promise.all(Object.entries(o.characters).map(async (x:[string,any])=>{
return this.GetInventory(`${account}/${x[1].name}`).then((ans)=>{
out.push(ans)
})
}))
return out
})
}
GetInventory = async (char_path: string):Promise<TricksterInventory> =>{
if(char_path.startsWith(":")) {
char_path = char_path.replace(":","")
}
return this.s.authed_request("GET", `item-manager/items/account/${char_path}`,undefined).then((ans:AxiosResponse)=>{
const o = ans.data
log.debug("GetInventory", o)
let name = ""
let id = ""
let wallet:TricksterWallet = {galders:0,state:0,job_img:""}
if(char_path.includes("/")) {
let [char, val] = Object.entries(o.characters)[0] as [string,any]
name = val.name
id = char
wallet = {
galders:val.galders as number,
state:val.state as number,
job_img: val.job_img as string
}
}else {
name = char_path
id = char_path
wallet = {
galders: 0,
state: 0,
job_img: "bank",
}
}
let out = {
name,
id,
wallet,
path: char_path,
items:(Object.entries(o.items) as any).map(([k, v]: [string, TricksterItem]):TricksterItem=>{
v.unique_id = Number(k)
return v
}),
} as TricksterInventory
return out
})
}
GetAccounts = async ():Promise<string[]> => {
return this.s.authed_request("POST", "accounts/list",undefined).then((ans:AxiosResponse)=>{
log.debug("GetAccounts", ans.data)
return ans.data.map((x:any)=>x.name)
})
}
GetLoggedin = async ():Promise<boolean> => {
return this.s.authed_request("POST", "accounts/list",undefined).then((ans:AxiosResponse)=>{
if(ans.status == 401) {
return false
}
if(ans.status == 200) {
return true
}
return false
})
}
}

View File

@ -1,4 +1,4 @@
import axios from "axios";
import axios, { AxiosResponse, Method } from "axios";
import qs from "qs";
import { getCookie, removeCookie } from "typescript-cookie";
@ -6,15 +6,20 @@ export interface Session {
user:string
xsrf:string
csrf:string
lto:string
authed_request:(verb:Method,url:string,data:any)=>Promise<any>
}
export const API_ROOT = "/lifeto/"
export const SITE_ROOT = "/lifeto/"
export const API_ROOT = "api/lifeto/"
const endpoint = (name:string)=>{
return API_ROOT + name
const login_endpoint = (name:string)=>{
return SITE_ROOT + name
}
const api_endpoint = (name:string)=>{
return SITE_ROOT+API_ROOT + name
}
export class LoginHelper {
user:string
@ -26,9 +31,8 @@ export class LoginHelper {
}
login = async ():Promise<TokenSession> =>{
removeCookie("XSRF-TOKEN")
removeCookie("lifeto_session", {path:'/'})
await sleep(1000)
return axios.get(endpoint("login"),{withCredentials:false})
return axios.get(login_endpoint("login"),{withCredentials:false})
.then(async (x)=>{
console.log(x)
if(x.data){
@ -37,7 +41,7 @@ export class LoginHelper {
}catch(e){
}
}
return axios.post(endpoint("login"),{
return axios.post(login_endpoint("login"),{
login:this.user,
password:this.pass,
redirectTo:"lifeto"
@ -45,41 +49,38 @@ export class LoginHelper {
.then(async (x)=>{
await sleep(100)
let xsrf= getCookie("XSRF-TOKEN")
let lifeto = getCookie("lifeto_session")
return new TokenSession(this.user,this.csrf!, xsrf!, lifeto!)
return new TokenSession(this.user,this.csrf!, xsrf!)
})
})
}
}
const sleep= async(ms:number)=> {
return new Promise(resolve => setTimeout(resolve, ms))
}
export class TokenSession {
export class TokenSession implements Session {
csrf:string
xsrf:string
lto:string
user:string
constructor(name:string, csrf:string, xsrf: string, lifeto:string){
constructor(name:string, csrf:string, xsrf: string){
this.user = name
this.csrf = csrf
this.xsrf = xsrf;
this.lto = lifeto;
}
authed_request = async (verb:string,url:string,data:any) => {
authed_request = async (verb:string,url:string,data:any):Promise<AxiosResponse> => {
let promise
switch (verb){
switch (verb.toLowerCase()){
case "post":
promise = axios.post(endpoint(url),data,this.genHeaders())
promise = axios.post(api_endpoint(url),data,this.genHeaders())
break;
case "postraw":
const querystring = qs.stringify(data)
promise = axios.post(endpoint(url),querystring,this.genHeaders())
promise = axios.post(api_endpoint(url),querystring,this.genHeaders())
break;
case "get":
default:
promise = axios.get(endpoint(url),this.genHeaders())
promise = axios.get(api_endpoint(url),this.genHeaders())
}
return promise.then(x=>{
if(x.data){
@ -93,7 +94,6 @@ export class TokenSession {
return y.split("=")[1].split(";")[0];
})
this.xsrf = cookies[0]
this.lto = cookies[1]
}
return x
})
@ -101,19 +101,8 @@ export class TokenSession {
genHeaders = ()=>{
const out = {
headers:{
Cookie:`XSRF-TOKEN=${this.xsrf}; lifeto_session=${this.lto}`,
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
Connection: "keep-alive",
"X-Requested-With":"XMLHttpRequest",
Host: "beta.lifeto.co",
"Alt-Used": "beta.lifeto.co",
Accept: "application/json",
"Update-Insecure-Requests": 1,
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0",
"Sec-Fetch-Mode":"navigate",
"Sec-Fetch-Dest":"document",
"Sec-Fetch-Site":"same-origin",
"Sec-Fetch-User":"?1",
"TE":"trailers"
},
withCredentials:true
}

View File

@ -1,46 +1,137 @@
import { HotTableProps } from "@handsontable/vue3/types"
import { TricksterInventory } from "./trickster"
import {ColumnInfo} from "./columns"
import {ColumnInfo, ColumnName, Columns, ColumnSorter, LazyColumn} from "./columns"
import { ColumnSettings } from "handsontable/settings"
import { PredefinedMenuItemKey } from "handsontable/plugins/contextMenu"
import { ref } from "vue"
export interface InventoryTableOptions {
columns: ColumnSet
tags: ColumnSet
}
export interface Mappable<T> {
map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
}
export class ColumnSet implements Set<ColumnInfo>, Mappable<ColumnInfo>{
s: Set<ColumnName> = new Set()
size: number;
dirty = ref(0)
constructor(i?:Iterable<ColumnInfo | ColumnName>){
if(i){
for (const a of i) {
this.s.add(LazyColumn(a))
}
}
this.size = 0
this.mark()
}
map<U>(callbackfn: (value: ColumnInfo, index: number, array: ColumnInfo[]) => U, thisArg?: any): U[] {
return Array.from(this.values()).map(callbackfn, thisArg)
}
[Symbol.iterator](): IterableIterator<ColumnInfo>{
return this.values()
}
[Symbol.toStringTag] = "ColumnSet";
entries(): IterableIterator<[ColumnInfo, ColumnInfo]>{
return Array.from(this.values()).map((x):[ColumnInfo,ColumnInfo]=>{return [x,x]}).values()
}
keys(): IterableIterator<ColumnInfo>{
return this.values()
}
forEach(callbackfn: (value: ColumnInfo, value2: ColumnInfo, set: Set<ColumnInfo>) => void, thisArg?: any): void{
Array.from(this.values()).forEach((v)=>{
if(this.has(v)) {
callbackfn(v, v, new Set(this.values()))
}
}, thisArg)
}
values(): IterableIterator<ColumnInfo>{
return Array.from(this.s.values()).sort(ColumnSorter).map((a, b)=>{
return Columns[a]
}).values()
}
mark() {
this.dirty.value = this.dirty.value + 1
this.size = this.s.size
}
add(value: ColumnInfo | ColumnName): this {
this.mark()
this.s.add(LazyColumn(value))
return this
}
clear(): void {
this.mark()
this.s.clear()
}
delete(value: ColumnInfo | ColumnName): boolean{
this.mark()
return this.s.delete(LazyColumn(value))
}
has(value: ColumnInfo | ColumnName): boolean{
return this.s.has(LazyColumn(value))
}
}
export class InventoryTable {
inventory:TricksterInventory
columns: ColumnInfo[]
inv!:TricksterInventory
o!: InventoryTableOptions
constructor(inv:TricksterInventory, ...columns:ColumnInfo[]) {
this.inventory = inv
this.columns = columns
constructor(inv:TricksterInventory, o:InventoryTableOptions) {
this.setInv(inv)
this.setOptions(o)
}
setOptions(o:InventoryTableOptions) {
this.o = o
}
setInv(inv:TricksterInventory) {
this.inv = inv
}
getTableColumnNames(): string[] {
return this.columns.map(x=>x.displayName)
return this.o.columns.map(x=>x.displayName)
}
getTableColumnSettings(): ColumnSettings[] {
return this.columns.map(x=>({
renderer: x.renderer ? x.renderer : "text",
dropdownMenu: x.filtering ? DefaultDropdownItems() : false,
readOnly: x.writable ? false : true,
selectionMode: x.writable ? "multiple" : "single"
}))
return this.o.columns.map(x=>({
renderer: x.renderer ? x.renderer : "text",
dropdownMenu: x.filtering ? DefaultDropdownItems() : false,
readOnly: x.writable ? false : true,
selectionMode: x.writable ? "multiple" : "single"
}))
}
getTableRows():any[][] {
return this.inventory.items.map((item)=>{
return this.columns.map(x=>x.getter(item))
return Object.values(this.inv.items)
.filter((item):boolean=>{
let found = false
if(this.o.tags.s.size > 0) {
let comparer = 1
for(const tag of this.o.tags.values()) {
let chk = tag.getter(item)
if(chk === comparer) {
found = true
}
}
}else {
found = true
}
return found
})
.map((item)=>{
return this.o.columns.map(x=>{
return x.getter(item)
})
})
}
BuildTable():TableRecipe {
const s = DefaultSettings()
const dat = this.getTableRows()
return {
data: this.getTableRows(),
data: dat,
settings: {
data: this.getTableRows(),
data: dat,
colHeaders:this.getTableColumnNames(),
columns:this.getTableColumnSettings(),
...s
@ -71,6 +162,7 @@ export const DefaultSettings = ():HotTableProps=>{
indicator: true,
headerAction: true,
},
className: 'htLeft',
contextMenu: false,
readOnlyCellClassName: "",
licenseKey:"non-commercial-and-evaluation",

View File

@ -11,6 +11,10 @@ export interface TricksterItem {
item_name: string;
item_id: number;
item_count: number;
item_desc: string;
item_use: string;
item_slots?: number;
item_min_level?: number;
is_equip?: boolean;
is_drill?: boolean;
item_expire_time?: ItemExpireTime;
@ -29,9 +33,10 @@ export interface TricksterWallet {
export interface TricksterInventory {
name:string
path:string
id:string
wallet?:TricksterWallet
items:TricksterItem[]
items:{[key:string]:TricksterItem}
}
@ -39,14 +44,11 @@ export interface TricksterInventory {
export const SampleData:{[key:string]:TricksterInventory} = {
aysheBoyfriend: {
name: sampleAyshe.characters[100047311].name,
items: Object.entries(sampleAyshe.items).map(([k, v]:[string, any])=>{
v.unique_id = k
return v
}),
items: sampleAyshe.items,
wallet: {
galders: sampleAyshe.characters[100047311].galders,
job_img: sampleAyshe.characters[100047311].job_img,
state: sampleAyshe.characters[100047311].state
}
}
} as any
}

View File

@ -3,6 +3,8 @@ import App from './App.vue'
import { globalCookiesConfig } from "vue3-cookies";
import { createPinia } from 'pinia';
import log from 'loglevel';
globalCookiesConfig({
expireTimes: "365d",
@ -12,4 +14,9 @@ globalCookiesConfig({
sameSite: "None",
});
createApp(App).mount('#app')
log.setLevel("debug")
const pinia = createPinia()
createApp(App).
use(pinia).
mount('#app')

View File

@ -1,4 +1,5 @@
<template>
<div> {{loginString}} </div>
<section class="login_modal">
<div class="login_field">
<label for="userName">Username: </label>
@ -28,39 +29,47 @@
</section>
</template>
<script lang="ts" setup>
import { useVModel } from '@vueuse/core'
const username = ref("")
const password = ref("")
const loginString = ref("not logged in")
const props = defineProps<{
username:string
password:string
}>()
const data = {
username: useVModel(props, 'username', defineEmits(['update:username'])),
password:useVModel(props, 'password', defineEmits(['update:password']))
const login = () => {
new LoginHelper(username.value, password.value).login()
.then((session)=>{
console.log(session, "adding to storage")
storage.AddSession(session)
}).catch((e)=>{
if(e.code == "ERR_BAD_REQUEST") {
alert("invalid username/password")
return
}
alert("unknown error, please report")
console.log(e)
})
}
const s = storage.GetSession()
const api = new LTOApiv0(s)
if (s != undefined) {
username.value = s.user
}
const updateLogin = () => {
api.GetLoggedin().then((res)=>{
if(res) {
loginString.value = "logged in as " + s.user
}
})
}
updateLogin()
</script>
<script lang="ts">
import { defineComponent, computed, PropType, defineProps, defineEmits} from 'vue';
import { defineComponent, computed, PropType, defineProps, defineEmits, ref} from 'vue';
import { LTOApiv0 } from '../lib/lifeto';
import { LoginHelper, Session } from '../lib/session';
import { storage } from '../session_storage';
export default defineComponent({
methods: {
login: function() {
new LoginHelper(this.username, this.password).login()
.then((session)=>{
console.log(session, "adding to storage")
storage.AddSession(session)
}).catch((e)=>{
if(e.code == "ERR_BAD_REQUEST") {
alert("invalid username/password")
return
}
alert("unknown error, please report")
console.log(e)
})
},
},
});
</script>

View File

@ -1,5 +1,5 @@
import { getCookie, setCookie} from 'typescript-cookie'
import { Session } from './lib/session'
import { Session, TokenSession } from './lib/session'
@ -10,53 +10,27 @@ export const nameCookie = (...s:string[]):string=>{
}
export class Storage {
GetSessions():{[key:string]:Session} {
const all_accounts = getCookie(nameCookie("all_accounts"))
const accounts = all_accounts?.split(",")
let out:{[key:string]:Session} = {};
for (const account in accounts) {
let tmp = {
user: account,
xsrf: getCookie(nameCookie("xsrf",account))!,
lto: getCookie(nameCookie("lto",account))!,
csrf: getCookie(nameCookie("csrf",account))!
}
out[account] = tmp
}
return out
}
RemoveSessions(...s:Session[]) {
for(const v of s) {
this.RemoveSession(v)
GetSession():Session {
const {user, xsrf, csrf} = {
user: getCookie(nameCookie("user"))!,
xsrf: getCookie(nameCookie("xsrf"))!,
csrf: getCookie(nameCookie("csrf"))!
}
return new TokenSession(user, xsrf, csrf)
}
RemoveSession(s:Session) {
const all_accounts = getCookie(nameCookie("all_accounts"))
let accounts = all_accounts?.split(",")
accounts = accounts ? accounts : []
accounts = [...new Set(accounts)]
accounts = accounts.filter(x=>x!=s.user)
setCookie(nameCookie("all_accounts"),accounts.join(","))
setCookie(nameCookie("lto",s.user), "")
setCookie(nameCookie("xsrf",s.user),"")
RemoveSession() {
setCookie(nameCookie("user"),"")
setCookie(nameCookie("xsrf"),"")
setCookie(nameCookie("csrf"),"")
}
AddSessions(...s:Session[]) {
for(const v of s) {
this.AddSession(v)
}
}
AddSession(s:Session) {
const all_accounts = getCookie(nameCookie("all_accounts"))
let accounts = all_accounts?.split(",")
accounts = accounts ? accounts : []
accounts.push(s.user)
accounts = [...new Set(accounts)]
setCookie(nameCookie("lto",s.user), s.lto)
setCookie(nameCookie("xsrf",s.user),s.xsrf)
setCookie(nameCookie("csrf",s.user),s.csrf)
setCookie(nameCookie("user"),s.user)
setCookie(nameCookie("xsrf"),s.xsrf)
setCookie(nameCookie("csrf"),s.csrf)
}
}

25
src/state/state.ts Normal file
View File

@ -0,0 +1,25 @@
import { defineStore, storeToRefs } from 'pinia'
import { BasicColumns, ColumnInfo, ColumnName, Columns, DetailsColumns, MoveColumns } from '../lib/columns'
import { ColumnSet } from '../lib/table'
import { TricksterInventory } from '../lib/trickster'
const _defaultColumn:(ColumnInfo| ColumnName)[] = [
...BasicColumns,
...MoveColumns,
...DetailsColumns,
]
export const useStore = defineStore('state', {
state: ()=> {
return {
accounts: new Set() as Set<string>,
invs: new Map() as Map<string,TricksterInventory>,
activeTable: "none",
screen: "default",
columns: new ColumnSet(_defaultColumn),
tags: new ColumnSet(),
}
}
})
export const useStoreRef = ()=>{return storeToRefs(useStore())};

View File

@ -12,10 +12,6 @@ export default defineConfig({
target: "https://beta.lifeto.co/",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/lifeto/, ''),
hostRewrite: "localhost:3001/lifeto",
cookieDomainRewrite:{
"*":"",
},
},
}
}