mirror of
				https://github.com/em-squared/5e-drs.git
				synced 2025-10-31 05:24:20 +00:00 
			
		
		
		
	refonte du grimoire personnel, suivi des emplacements de sorts par niveau
This commit is contained in:
		
							parent
							
								
									7cf83baed3
								
							
						
					
					
						commit
						9dae3aec37
					
				
					 6 changed files with 180 additions and 27 deletions
				
			
		|  | @ -5,6 +5,7 @@ export default { | ||||||
| 
 | 
 | ||||||
|   state: { |   state: { | ||||||
|     spells: [], |     spells: [], | ||||||
|  |     spellSlots: [] | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|   getters: { |   getters: { | ||||||
|  | @ -32,6 +33,7 @@ export default { | ||||||
| 			if(localStorage.getItem('mySpells') && localStorage.getItem('mySpells') !== undefined) { | 			if(localStorage.getItem('mySpells') && localStorage.getItem('mySpells') !== undefined) { | ||||||
|         let localStorageData = JSON.parse(localStorage.getItem('mySpells')) |         let localStorageData = JSON.parse(localStorage.getItem('mySpells')) | ||||||
|         state.spells = localStorageData.spells |         state.spells = localStorageData.spells | ||||||
|  |         state.spellSlots = localStorageData.spellSlots | ||||||
| 			} | 			} | ||||||
| 		}, | 		}, | ||||||
|     setSpells: (state, payload) => { |     setSpells: (state, payload) => { | ||||||
|  | @ -58,6 +60,9 @@ export default { | ||||||
|         } |         } | ||||||
|       }) |       }) | ||||||
|     }, |     }, | ||||||
|  |     setSpellSlots: (state, payload) => { | ||||||
|  |       state.spellSlots = payload | ||||||
|  |     }, | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,19 +2,108 @@ | ||||||
|   <main class="page content"> |   <main class="page content"> | ||||||
|     <div class="theme-default-content"> |     <div class="theme-default-content"> | ||||||
|       <div v-if="spells.length > 0"> |       <div v-if="spells.length > 0"> | ||||||
|         <masonry class="d-print-none" :cols="{'default': 2, 960: 1}" :gutter="24"> |         <div class="d-print-none mb-12"> | ||||||
|           <SpellCard v-for="(spell, idx) in spells" :spell="spell" :showActions="true" :key="idx"> | 
 | ||||||
|           </SpellCard> |           <v-dialog v-model="spellCard" max-width="660"> | ||||||
|         </masonry> |             <v-card v-if="selectedSpell"> | ||||||
|         <div class="d-none d-print-block" v-for="spell in spells"> |               <v-card-title class="headline"> | ||||||
|           <div> |                 {{selectedSpell.title}} | ||||||
|             <h2 class="d-flex align-center"> |                 <v-spacer></v-spacer> | ||||||
|  |                 <v-btn icon @click="spellCard = false"><v-icon>mdi-close</v-icon></v-btn> | ||||||
|  |               </v-card-title> | ||||||
|  | 
 | ||||||
|  |               <v-card-text> | ||||||
|  |                 <Spell :spell="selectedSpell" :isList="true" :hideTitle="true" /> | ||||||
|  |               </v-card-text> | ||||||
|  |             </v-card> | ||||||
|  |           </v-dialog> | ||||||
|  | 
 | ||||||
|  |           <v-data-table | ||||||
|  |             class="data-table" | ||||||
|  |             :headers="headers" | ||||||
|  |             :items="spells" | ||||||
|  |             item-key="key" | ||||||
|  |             :sort-by="sortBy" | ||||||
|  |             :sort-desc="sortDesc" | ||||||
|  |             group-by="frontmatter.level" | ||||||
|  |             must-sort | ||||||
|  |             :items-per-page="-1" | ||||||
|  |             hide-default-footer | ||||||
|  |           > | ||||||
|  | 
 | ||||||
|  |             <template v-slot:group.header="{ group, headers, isOpen, toggle }"> | ||||||
|  |               <td class="group-header" :colspan="headers.length"> | ||||||
|  |                 <div class="d-block d-md-flex align-center"> | ||||||
|  |                   <div class="mr-md-12"> | ||||||
|  |                     <v-btn dark small depressed icon @click.stop="toggle"><v-icon v-if="isOpen">mdi-minus</v-icon><v-icon v-else>mdi-plus</v-icon></v-btn> | ||||||
|  |                     <span class="subtitle-2"><strong>{{ displayLevel(group) }}</strong></span> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="mx-md-12"> | ||||||
|  |                     <div v-if="group > 0" style="width: 125px;"> | ||||||
|  |                       <v-text-field dark label="Emplacements" type="number" min="0" v-model="spellSlots[group]" @input="onInputSpellSlots"></v-text-field> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="ml-md-12"> | ||||||
|  |                     <div class="d-flex" v-if="spellSlots[group] > 0"> | ||||||
|  |                       <div v-for="(slot, idx) in Number(spellSlots[group])" :key="idx"> | ||||||
|  |                         <v-checkbox dark></v-checkbox> | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               </td> | ||||||
|  |             </template> | ||||||
|  | 
 | ||||||
|  |             <template v-slot:item.title="{ item }"> | ||||||
|  |               <span class="cursor-pointer subtitle-2" @click.stop="openSpellDetails(item)">{{ item.title }}</span> | ||||||
|  |             </template> | ||||||
|  | 
 | ||||||
|  |             <template v-slot:item.frontmatter.level="{ item }"> | ||||||
|  |               <span v-if="item.frontmatter.level == 0">Tour de magie</span> | ||||||
|  |               <span v-else>{{ item.frontmatter.level }}</span> | ||||||
|  |             </template> | ||||||
|  | 
 | ||||||
|  |             <template v-slot:item.frontmatter.concentration="{ item }"> | ||||||
|  |               <span v-if="item.frontmatter.concentration">concentration</span> | ||||||
|  |             </template> | ||||||
|  | 
 | ||||||
|  |             <template v-slot:item.frontmatter.ritual="{ item }"> | ||||||
|  |               <span v-if="item.frontmatter.ritual">rituel</span> | ||||||
|  |             </template> | ||||||
|  | 
 | ||||||
|  |             <template v-slot:item.frontmatter.components="{ item }"> | ||||||
|  |               <template v-if="item.frontmatter.components"> | ||||||
|  |                 <template v-if="item.frontmatter.components.verbal">V</template><template v-if="item.frontmatter.components.verbal && (item.frontmatter.components.somatic || item.frontmatter.components.material)">,</template> | ||||||
|  |                 <template v-if="item.frontmatter.components.somatic">S</template><template v-if="item.frontmatter.components.somatic && item.frontmatter.components.material">,</template> | ||||||
|  |                 <template v-if="item.frontmatter.components.material">M</template> | ||||||
|  |               </template> | ||||||
|  |             </template> | ||||||
|  | 
 | ||||||
|  |             <template v-slot:item.actions="{ item }"> | ||||||
|  |               <v-btn class="d-print-none mr-2" small depressed icon @click.stop="openSpellDetails(item)"><v-icon>mdi-eye</v-icon></v-btn> | ||||||
|  |               <v-btn class="d-print-none mr-2" small depressed link icon :to="{ path: '/creation-de-sort/', query: { key: item.key } }"><v-icon>mdi-pencil</v-icon></v-btn> | ||||||
|  |               <v-btn color="error" class="d-print-none" small depressed icon @click="$store.commit('mySpells/removeSpell', item)"><v-icon>mdi-delete</v-icon></v-btn> | ||||||
|  |             </template> | ||||||
|  | 
 | ||||||
|  |           </v-data-table> | ||||||
|  |         </div> | ||||||
|  |         <div class="d-none d-print-block"> | ||||||
|  |           <template v-for="(n, level) in 9" v-if="hasSpellOfLevel(level)"> | ||||||
|  |             <h2 v-if="level == 0">Tours de magie</h2> | ||||||
|  |             <h2 v-else>Sorts de niveau {{ level }}</h2> | ||||||
|  |             <div class="column-count-2"> | ||||||
|  |               <div v-for="spell in spells"> | ||||||
|  |                 <template v-if="spell.frontmatter.level == level"> | ||||||
|  |                   <h3 class="d-flex align-center title"> | ||||||
|                     <div class="mr-4">{{ spell.title }}</div> |                     <div class="mr-4">{{ spell.title }}</div> | ||||||
|                     <v-btn class="d-print-none mr-2" small depressed link :to="{ path: '/creation-de-sort/', query: { key: spell.key } }"><v-icon left>mdi-pencil</v-icon> Modifier</v-btn> |                     <v-btn class="d-print-none mr-2" small depressed link :to="{ path: '/creation-de-sort/', query: { key: spell.key } }"><v-icon left>mdi-pencil</v-icon> Modifier</v-btn> | ||||||
|                     <v-btn color="error" class="d-print-none" small depressed @click="$store.commit('mySpells/removeSpell', spell)"><v-icon left>mdi-delete</v-icon> Supprimer</v-btn> |                     <v-btn color="error" class="d-print-none" small depressed @click="$store.commit('mySpells/removeSpell', spell)"><v-icon left>mdi-delete</v-icon> Supprimer</v-btn> | ||||||
|             </h2> |                   </h3> | ||||||
|           </div> |  | ||||||
|                   <Spell :spell="spell" :isList="true" :hideTitle="true" /> |                   <Spell :spell="spell" :isList="true" :hideTitle="true" /> | ||||||
|  |                 </template> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </template> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       <template v-else> |       <template v-else> | ||||||
|  | @ -39,20 +128,72 @@ export default { | ||||||
| 
 | 
 | ||||||
|   data () { |   data () { | ||||||
|     return { |     return { | ||||||
| 
 |       sortBy: 'frontmatter.level', | ||||||
|  |       sortDesc: false, | ||||||
|  |       headers: [ | ||||||
|  |         { text: "Nom", align: 'start', sortable: false, value: 'title' }, | ||||||
|  |         { text: "Niveau", align: 'center', sortable: false, value: 'frontmatter.level' }, | ||||||
|  |         { text: "École", align: 'start', sortable: false, value: 'frontmatter.school' }, | ||||||
|  |         { text: "Temps d'incantation", align: 'start', sortable: false, value: 'frontmatter.casting_time' }, | ||||||
|  |         { text: "Durée", align: 'start', sortable: false, value: 'frontmatter.duration' }, | ||||||
|  |         { text: "Concentration", align: 'center', sortable: false, value: 'frontmatter.concentration' }, | ||||||
|  |         { text: "Rituel", align: 'center', sortable: false, value: 'frontmatter.ritual' }, | ||||||
|  |         { text: "Composantes", align: 'center', sortable: false, value: 'frontmatter.components' }, | ||||||
|  |         { text: "", align: 'center', sortable: false, value: 'actions' }, | ||||||
|  |       ], | ||||||
|  |       spellCard: false, | ||||||
|  |       selectedSpell: null | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|   computed: { |   computed: { | ||||||
|     spells () { |     spells () { | ||||||
|       return this.$store.state.mySpells.spells |       return this.$store.state.mySpells.spells | ||||||
|  |     }, | ||||||
|  |     spellSlots: { | ||||||
|  |       get () { | ||||||
|  |         return this.$store.state.mySpells.spellSlots | ||||||
|  |       }, | ||||||
|  |       set (value) { | ||||||
|  |         this.$store.commit('mySpells/setSpells', value) | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|   methods: { |   methods: { | ||||||
|  |     displayLevel (level) { | ||||||
|  |       if (level == 0 || level == "0") { | ||||||
|  |         return 'Tours de magie' | ||||||
|  |       } else { | ||||||
|  |         return 'Sorts de niveau ' + level | ||||||
|       } |       } | ||||||
|  |     }, | ||||||
|  |     onInputSpellSlots () { | ||||||
|  |       this.$store.commit('mySpells/setSpellSlots', this.spellSlots) | ||||||
|  |     }, | ||||||
|  |     openSpellDetails (spell) { | ||||||
|  |       this.selectedSpell = spell | ||||||
|  |       this.spellCard = true | ||||||
|  |     }, | ||||||
|  |     hasSpellOfLevel (level) { | ||||||
|  |       for (let spell of this.spells) { | ||||||
|  |         if (spell.frontmatter.level == level) { | ||||||
|  |           return true | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       return false | ||||||
|  |     } | ||||||
|  |   }, | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <style lang="scss"> | <style lang="scss"> | ||||||
|  | @import "../styles/colors"; | ||||||
|  | .group-header { | ||||||
|  |   background-color: $color-dragon; | ||||||
|  |   color: #fff; | ||||||
|  | } | ||||||
|  | .cursor-pointer { | ||||||
|  |   cursor: pointer; | ||||||
|  | } | ||||||
| </style> | </style> | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ export default { | ||||||
| 
 | 
 | ||||||
|   methods: { |   methods: { | ||||||
|     download () { |     download () { | ||||||
|       saveAs(new Blob([JSON.stringify(this.$store.state.myMagicItems.magicItems)], { |       saveAs(new Blob([JSON.stringify(this.$store.state.myMagicItems)], { | ||||||
|           type: "text/plain;charset=utf-8" |           type: "text/plain;charset=utf-8" | ||||||
|       }), "objets-magiques.json") |       }), "objets-magiques.json") | ||||||
|     }, |     }, | ||||||
|  | @ -56,15 +56,15 @@ export default { | ||||||
|       reader.onload = function() { |       reader.onload = function() { | ||||||
|         let result = JSON.parse(reader.result) |         let result = JSON.parse(reader.result) | ||||||
|         let isValid = true |         let isValid = true | ||||||
|         if (result.length >= 1) { |         if (result.magicItems && result.magicItems.length >= 1) { | ||||||
|           for (var s of result) { |           for (var s of result.magicItems) { | ||||||
|             if (s.pid !== 'magicItem') { |             if (s.pid !== 'magicItem') { | ||||||
|               isValid = false |               isValid = false | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         if (isValid) { |         if (isValid) { | ||||||
|           self.$store.commit('myMagicItems/setMagicItems', result) |           self.$store.commit('myMagicItems/setMagicItems', result.magicItems) | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ export default { | ||||||
| 
 | 
 | ||||||
|   methods: { |   methods: { | ||||||
|     download () { |     download () { | ||||||
|       saveAs(new Blob([JSON.stringify(this.$store.state.myMonsters.monsters)], { |       saveAs(new Blob([JSON.stringify(this.$store.state.myMonsters)], { | ||||||
|           type: "text/plain;charset=utf-8" |           type: "text/plain;charset=utf-8" | ||||||
|       }), "bestiaire.json") |       }), "bestiaire.json") | ||||||
|     }, |     }, | ||||||
|  | @ -56,15 +56,15 @@ export default { | ||||||
|       reader.onload = function() { |       reader.onload = function() { | ||||||
|         let result = JSON.parse(reader.result) |         let result = JSON.parse(reader.result) | ||||||
|         let isValid = true |         let isValid = true | ||||||
|         if (result.length >= 1) { |         if (result.monsters && result.monsters.length >= 1) { | ||||||
|           for (var s of result) { |           for (var s of result.monsters) { | ||||||
|             if (s.pid !== 'monster') { |             if (s.pid !== 'monster') { | ||||||
|               isValid = false |               isValid = false | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         if (isValid) { |         if (isValid) { | ||||||
|           self.$store.commit('myMonsters/setMonsters', result) |           self.$store.commit('myMonsters/setMonsters', result.monsters) | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -45,7 +45,7 @@ export default { | ||||||
| 
 | 
 | ||||||
|   methods: { |   methods: { | ||||||
|     download () { |     download () { | ||||||
|       saveAs(new Blob([JSON.stringify(this.$store.state.mySpells.spells)], { |       saveAs(new Blob([JSON.stringify(this.$store.state.mySpells)], { | ||||||
|           type: "text/plain;charset=utf-8" |           type: "text/plain;charset=utf-8" | ||||||
|       }), "grimoire.json") |       }), "grimoire.json") | ||||||
|     }, |     }, | ||||||
|  | @ -58,15 +58,18 @@ export default { | ||||||
|       reader.onload = function() { |       reader.onload = function() { | ||||||
|         let result = JSON.parse(reader.result) |         let result = JSON.parse(reader.result) | ||||||
|         let isValid = true |         let isValid = true | ||||||
|         if (result.length >= 1) { |         if (result.spells && result.spells.length >= 1) { | ||||||
|           for (var s of result) { |           for (var s of result.spells) { | ||||||
|             if (s.pid !== 'spell') { |             if (s.pid !== 'spell') { | ||||||
|               isValid = false |               isValid = false | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|         if (isValid) { |         if (isValid) { | ||||||
|           self.$store.commit('mySpells/setSpells', result) |           self.$store.commit('mySpells/setSpells', result.spells) | ||||||
|  |           if (result.spellSlots) { | ||||||
|  |             self.$store.commit('mySpells/setSpellSlots', result.spellSlots) | ||||||
|  |           } | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,8 @@ | ||||||
| .page.content { | .page.content { | ||||||
|  |   .column-count-2 { | ||||||
|  |     column-count: 2; | ||||||
|  |     column-gap: 25pt; | ||||||
|  |   } | ||||||
|   .column-count-3 { |   .column-count-3 { | ||||||
|     column-count: 3; |     column-count: 3; | ||||||
|     margin-bottom: 12px; |     margin-bottom: 12px; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Maxime Moraine
						Maxime Moraine