=
index.vue
<template>
<div>
<!-- Table Container Card -->
<b-card no-body class="mb-0">
<div class="m-2">
<!-- Table Top -->
<b-row>
<!-- Per Page -->
<b-col cols="12" md="6" class="d-flex align-items-center justify-content-start mb-1 mb-md-0">
<label>Show</label>
<b-form-select
v-model="queryBody.per_page"
:options="pageOptions"
:clearable="false"
@change="changePageCount"
class="per-page-selector d-inline-block mx-50"
/>
<label>entries</label>
</b-col>
<!-- Per Page -->
<!-- Search -->
<b-col cols="12" md="6">
<div class="d-flex align-items-center justify-content-end">
<b-input-group size="md" class="mr-2">
<b-form-input
v-model="filter"
type="search"
placeholder="Type here to Search ..."
v-on:keyup="findData"
@search="clearSearch"
></b-form-input>
<b-input-group-append>
<b-button
:disabled="!filter"
@click="findData"
variant="primary"
>Search</b-button>
</b-input-group-append>
</b-input-group>
<router-link :to="{name: 'card_create'}">
<b-button variant="primary">
<span class="text-nowrap">Add</span>
</b-button>
</router-link>
</div>
</b-col>
</b-row>
</div>
<b-table
:busy="isTableLoading"
class="position-relative"
:items="itemsData"
responsive
:fields="fields"
primary-key="id"
no-local-sorting
@sort-changed="customSorting"
show-empty
empty-text="No matching records found"
>
<template v-slot:table-busy>
<div class="text-center text-primary my-2">
<b-spinner class="align-middle"></b-spinner>
</div>
</template>
<template v-slot:cell(actions)="row">
<b-dropdown variant="link" no-caret v-if="row.item.id !== -1">
<template #button-content>
<font-awesome-icon
:icon="['fas', 'ellipsis-vertical']"
class="align-middle text-body"
/>
</template>
<b-dropdown-item @click="viewCard(row.item.name, row.item.id)">
<font-awesome-icon :icon="['fas', 'eye']" />
</b-dropdown-item>
<b-dropdown-item >
<router-link :to="{ name: 'card_edit', params: { id: row.item.id }}">
<font-awesome-icon icon="pen" class="mr-1"></font-awesome-icon>
</router-link>
</b-dropdown-item>
<b-dropdown-item @click="openModal(row.item)">
<font-awesome-icon :icon="['fas', 'trash']" />
</b-dropdown-item>
</b-dropdown>
</template>
</b-table>
<div class="mx-2 mb-2">
<b-row>
<b-col cols="12" sm="6" class="d-flex align-items-center justify-content-center justify-content-sm-start">
<span class="text-muted">
Showing {{ pageMeta.from }} to {{ pageMeta.to }} of {{ totalRows }} entries
<span v-if="filter">(filtered from {{ rowsCount }} total entries)</span>
</span>
</b-col>
<!-- Pagination -->
<b-col cols="12" sm="6" class="d-flex align-items-center justify-content-center justify-content-sm-end">
<b-pagination
v-model="queryBody.page"
:total-rows="totalRows"
:per-page="queryBody.per_page"
@page-change="pagination"
first-number
last-number
class="mb-0 mt-1 mt-sm-0"
prev-class="prev-item"
next-class="next-item"
>
<template #prev-text>
<font-awesome-icon :icon="['fas', 'chevron-left']" />
</template>
<template #next-text>
<font-awesome-icon :icon="['fas', 'chevron-right']" />
</template>
</b-pagination>
</b-col>
</b-row>
</div>
</b-card>
<div></div>
<b-modal
hide-footer=true
v-model="showModal"
id="confirmation_modal"
:title="infoModal.title"
centered
size="md"
@hide="resetInfoModal"
>
<p v-html="infoModal.message" class="float-left"></p>
<div class="mt-3 d-flex justify-content-end">
<b-button class="" @click="cancel('confirmation_modal')">Cancel</b-button>
<b-button
variant="primary"
v-on:click="deleteCard(infoModal.id)"
style="margin-left: 8px;"
>Yes</b-button>
</div>
</b-modal>
<div>
</div>
</div>
</template>
<script>
import { ref, reactive, computed, watchEffect } from 'vue';
import { useStore } from 'vuex';
import axios from 'axios';
export default {
name: 'Card Index',
components: {
},
setup() {
const store = useStore();
const queryBody = reactive({
sort_by: '',
order: '',
page: 1,
per_page: 5,
});
const infoModal = reactive ({
id: '',
title: '',
content:{},
message:"",
});
const fields = reactive([
{ key: 'id', label: 'ID' },
{ key: 'name', label: 'Name' },
{ key: 'description', label: 'Description' },
{ key: 'actions', label: 'Actions' },
]);
const isTableLoading = ref(false);
const pageOptions = [5, 10, 25, 50, 100];
const totalRows = ref(1);
const filter = ref('');
const itemsData = ref([]);
const lastPage = ref(1);
const rowsCount = ref(0);
const showModal = ref(false);
const rowItem=ref({});
const refetchData = () => {
getData(queryBody);
};
const deleteCard =(data_id) => {
closeModal();
filter.value='';
axios
.delete('/cards/'+data_id)
.then(response => {
formateResponse(response.data);
})
.catch(error => {
console.log(error);
});
};
const pageMeta = computed(() => {
const from = (queryBody.page - 1) * queryBody.per_page + 1;
const to =
queryBody.page * queryBody.per_page > totalRows.value
? totalRows.value
: queryBody.page * queryBody.per_page;
return { from, to };
});
const changePageCount = (per_page) => {
queryBody.page = 1;
queryBody.per_page = per_page;
getData(queryBody);
};
const findData = () => {
queryBody.query = filter.value;
getData(queryBody);
};
const openModal = (data)=> {
infoModal.content =data;
infoModal.id=data.id;
infoModal.title='Confirmation to Remove Card?';
infoModal.message ='Are you sure you want to remove the card \'' + data.name + '\'?';
showModal.value = true;
};
const closeModal = ()=> {
showModal.value = false;
};
const resetInfoModal = () => {
infoModal.id="";
infoModal.content = null;
infoModal.title='';
infoModal.message='';
closeModal();
};
const cancel = () => {
showModal.value=false;
// this.$bvModal.hide(model_name);
resetInfoModal();
};
const customSorting = (ctx) => {
if (ctx.sortBy == '' || ctx.sortBy == null) {
return;
}
queryBody.order = ctx.sortDesc ? 'asc' : 'desc';
queryBody.sort_by = ctx.sortBy;
queryBody.page = 1;
getData(queryBody);
};
const clearSearch = (event) => {
if (event.target.value === '') {
if (!filter.value) {
queryBody.page = 1;
queryBody.per_page = 10;
delete queryBody.query;
getData(queryBody);
}
}
};
const formateResponse = (result) => {
let si_no = (queryBody.page - 1) * queryBody.per_page + 1;
let card_data = result.data.map((item, index) => ({
...item,
si_no: si_no + index + 1,
}));
// console.log(store._actions);
store.dispatch('card/allCards', card_data).then(() => {
itemsData.value = store.getters['card/getAllCards'];
});
let pagination = result;
queryBody.page = parseInt(pagination.current_page);
queryBody.per_page = parseInt(pagination.per_page, 10);
lastPage.value = pagination.last_page;
totalRows.value = pagination.total;
rowsCount.value = pagination.rows_count;
// if (itemsData.value.length === 1) {
// itemsData.value.push({
// id: -1,
// name: '',
// });
// }
};
const deleteEmptyKeys = (data) => {
let query = {};
for (let key in data) {
data[key] !== '' ? (query[key] = data[key]) : '';
}
return query;
};
const pagination =(pageNumber)=> {
queryBody.page=pageNumber;
getData(this.queryBody);
};
const getData = (params) => {
const queryParams = {
params: deleteEmptyKeys(params),
};
isTableLoading.value = true;
axios
.get('/cards', queryParams)
.then((response) => {
formateResponse(response.data.data);
})
.catch((error) => {
console.error('Error fetching user data:', error);
})
.finally(() => {
isTableLoading.value = false;
});
};
watchEffect(() => {
getData(queryBody);
});
return {
queryBody,
rowItem,
pageOptions,
totalRows,
filter,
itemsData,
lastPage,
rowsCount,
refetchData,
changePageCount,
findData,
customSorting,
fields,
clearSearch,
deleteEmptyKeys,
getData,
formateResponse,
pageMeta,
pagination,
isTableLoading,
openModal,
closeModal,
deleteCard,
showModal,
resetInfoModal,
cancel,
infoModal
};
},
};
</script>
<style>
.per-page-selector {
width: 90px;
}
.custom-table {
overflow-x: auto;
white-space: nowrap !important;
}
.loader-container {
display: flex;
justify-content: center;
align-items: center;
height: 100px; /* Adjust the height as needed */
}
</style>
edit.vue
<template>
<div>
<b-form
class="p-2"
@submit.prevent="saveChanges"
>
<b-row>
<b-col cols="12" >
<b-form-group
label="Account Type"
label-for="account_type"
>
<b-form-select
id="account_type"
v-model="form_data.account_type"
:options="accountTypeOptions"
required
/>
</b-form-group>
<b-form-group
label="Name"
label-for="name"
>
<b-form-input
id="name"
v-model="form_data.name"
required
placeholder="Enter the name"
/>
</b-form-group>
<b-form-group
label="Description"
label-for="description"
>
<b-form-textarea
id="description"
v-model="form_data.description"
rows="3"
placeholder="Enter the description"
/>
</b-form-group>
</b-col>
<b-col cols="12" >
<b-form-group
label="Formula"
label-for="formula"
>
<b-form-textarea
id="formula"
v-model="form_data.formula"
rows="3"
placeholder="Enter the formula"
/>
</b-form-group>
</b-col>
<b-col cols="12" >
<b-form-group
label="UPI ID"
label-for="upi_id"
>
<b-form-input
id="upi_id"
v-model="form_data.upi_id"
required
placeholder="Enter the UPI ID"
/>
</b-form-group>
</b-col>
</b-row>
<b-button type="submit" variant="primary">Update</b-button>
</b-form>
</div>
</template>
<script>
import axios from 'axios';
export default {
components: {
},
data() {
return {
accountTypeOptions: [
{ value: 'savings', text: 'Savings' },
{ value: 'credit_card', text: 'Credit Card' },
{ value: 'loan', text: 'Loan' }
],
form_data: {
account_type: '', // Will be set based on the selected option
name: '',
description: '',
formula: '',
upi_id: ''
}
};
},
mounted(){
this.fetchData();
},
computed: {
},
methods:{
fetchData() {
axios.get('/cards/'+this.$route.params.id+'/edit')
.then((response) => {
let result =response.data.data;
this.form_data.account_type=result.account_type;
this.form_data.name=result.name;
this.form_data.description=result.description;
this.form_data.formula=result.formula;
this.form_data.upi_id=result.upi_id;
})
.catch((error) => {
// Handle errors here
console.error('Error fetching user data:', error);
});
},
saveChanges() {
axios
.put('cards/'+this.$route.params.id, this.form_data)
.then(response => {
this.$store.dispatch('card/allCards', response.data.data);
this.$router.push({ name: 'card_index' });
})
.catch(err => {
console.log(err);
});
},
},
};
</script>
create.vue
<template>
<div>
<b-form
class="p-2"
@submit.prevent="saveChanges"
>
<b-row>
<b-col cols="12" >
<b-form-group
label="Account Type"
label-for="account_type"
>
<b-form-select
id="account_type"
v-model="form_data.account_type"
:options="accountTypeOptions"
required
/>
</b-form-group>
<b-form-group
label="Name"
label-for="name"
>
<b-form-input
id="name"
v-model="form_data.name"
required
placeholder="Enter the name"
/>
</b-form-group>
<b-form-group
label="Description"
label-for="description"
>
<b-form-textarea
id="description"
v-model="form_data.description"
rows="3"
placeholder="Enter the description"
/>
</b-form-group>
</b-col>
<b-col cols="12" >
<b-form-group
label="Formula"
label-for="formula"
>
<b-form-textarea
id="formula"
v-model="form_data.formula"
rows="3"
placeholder="Enter the formula"
/>
</b-form-group>
</b-col>
<b-col cols="12" >
<b-form-group
label="UPI ID"
label-for="upi_id"
>
<b-form-input
id="upi_id"
v-model="form_data.upi_id"
required
placeholder="Enter the UPI ID"
/>
</b-form-group>
</b-col>
</b-row>
<b-button type="submit" variant="primary">Create</b-button>
</b-form>
</div>
</template>
<script>
import axios from 'axios';
export default {
components: {
},
data() {
return {
accountTypeOptions: [
{ value: 'savings', text: 'Savings' },
{ value: 'credit_card', text: 'Credit Card' },
{ value: 'loan', text: 'Loan' }
],
form_data: {
account_type: '', // Will be set based on the selected option
name: '',
description: '',
formula: '',
upi_id: ''
}
};
},
mounted(){
},
computed: {
},
methods:{
saveChanges() {
axios
.post('cards', this.form_data)
.then(response => {
this.$store.dispatch('card/allCards', response.data.data);
this.$router.push({ name: 'card_index' });
})
.catch(err => {
console.log(err);
});
},
},
};
</script>
store/actions.js
export default {
allCards({ commit }, cards) {
commit('SET_ALL_CARDS', cards);
},
}
store/card.js
import state from './state.js'
import mutations from './mutations.js'
import actions from './actions.js'
import getters from './getters.js'
export default {
namespaced: true,
state,
mutations,
actions,
getters
}
store/getters.js
export default {
getAllCards(state) {
return state.cards;
},
}
store/mutations.js
export default {
SET_ALL_CARDS(state, cards) {
state.cards = cards;
},
}
store/state.js
export default {
cards: [],
}
router.js
const router=[
{
path: '/cards/list',
name: 'card_index',
component: () =>
import ("./Index.vue")
},
{
path: '/cards/create',
name: 'card_create',
component: () =>
import ("./Create.vue")
},
{
path: "/card/edit/:id",
name: 'card_edit',
component: () =>
import ("./Edit")
},
];
export default router;
in main router.js
import { createRouter, createWebHistory } from 'vue-router';
import HomePage from './components/HomePage';
import cardRouter from './pages/cards/router';
import childRouter from './pages/children/router'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/home',
name: 'Home',
component: HomePage
},
{
path: '/sample',
name: 'Sample',
component: () =>
import (/* web pack chunk sample page */"./components/SamplePage")
},
{
path: '/table-dynamic-option',
name: 'TableDynamicOption',
component: () =>
import ("./components/TableDynamicOption")
},
{
path: '/table-dynamic-composition',
name: 'TableDynamicComposition',
component: () =>
import ("./components/TableDynamicComposition")
},
{
path: '/vue-slots',
name: 'VueSlots',
component: () =>
import ("./pages/VueSlots")
},
...cardRouter,
...childRouter,
{
path: "/404",
alias: "/:pathMatch(.*)*", // Custom regular expression for catch-all
name: "notFound",
component: () =>
import(/* webpackChunkName: "NotFound" */ "./views/NotFound")
}
]
});
export default router;
in main
store/index.js
import { createStore } from 'vuex';
import cardModule from '../pages/cards/store/card.js';
const store = createStore({
modules: {
card: cardModule, // Add the card module under the 'card' namespace
},
});
export default store;
old vuex
import { createStore } from 'vuex';
const store = createStore({
state: {
cards: [],
},
mutations: {
SET_ALL_CARDS(state, cards) {
state.cards = cards;
},
},
actions: {
allCards({ commit }, cards) {
commit('SET_ALL_CARDS', cards);
}
},
getters: {
getAllCards(state) {
return state.cards;
},
},
});
export default store;
=
=
No comments:
Post a Comment