build datatable

This commit is contained in:
Casey Wittrock 2025-10-23 17:08:17 -05:00
parent 6b0a3d9fa9
commit 73a3b67e0f
5 changed files with 141 additions and 65 deletions

View File

@ -1,42 +1,33 @@
import DataUtils from "./utils";
class Api { class Api {
static async getAddresses(fields = []) {
const addressNames = await frappe.db.get_list("Address", { fields });
console.log("DEBUG: API - Fetched Address list: ", addressNames);
return addressNames;
}
static async getDetailedAddress(name) {
const address = await frappe.db.get_doc("Address", name);
console.log("DEBUG: API - Fetched Detailed Address: ", address);
return address;
}
static async getCustomerList(fields = []) {
const customers = await frappe.db.get_list("Customer", { fields });
console.log("DEBUG: API - Fetched Customer list: ", customers);
return customers;
}
static async getDetailedCustomer(name) {
const customer = await frappe.db.get_doc("Customer", name);
console.log("DEBUG: API - Fetched Detailed Customer: ", customer);
return customer;
}
static async getClientDetails() { static async getClientDetails() {
const data = []; // const data = [];
const addresses = await this.getAddresses(); // const addresses = await this.getDocsList("Address");
for (const addr of addresses) { // for (const addr of addresses) {
const clientDetail = {}; // const clientDetail = {};
const fullAddress = await this.getDetailedAddress(addr["name"] || addr["Name"]); // const fullAddress = await this.getDetailedDoc("Address", addr["name"] || addr["Name"]);
const customer = await this.getDetailedCustomer(fullAddress["links"][0]["link_name"]); // const customer = await this.getDetailedCustomer(fullAddress["links"][0]["link_name"]);
clientDetail.customer = customer; // clientDetail.customer = customer;
clientDetail.address = fullAddress; // clientDetail.address = fullAddress;
data.push(clientDetail); // data.push(clientDetail);
} // }
console.log("DEBUG: API - Fetched Client Details: ", data); // console.log("DEBUG: API - Fetched Client Details: ", data);
const data = DataUtils.dummyClientData;
return data; return data;
} }
static async getDocsList(doctype, fields = []) {
const docs = await frappe.db.get_list(doctype, { fields });
console.log(`DEBUG: API - Fetched ${doctype} list: `, docs);
return docs;
}
static async getDetailedDoc(doctype, name) {
const doc = await frappe.db.get_doc(doctype, name);
console.log(`DEBUG: API - Fetched Detailed ${doctype}: `, doc);
return doc;
}
} }
export default Api; export default Api;

View File

@ -1,4 +1,4 @@
<template lang=""> <template lang="html">
<div id="paging-controls"> <div id="paging-controls">
<p>Show rows:</p> <p>Show rows:</p>
<button class="page-num-button">25</button> <button class="page-num-button">25</button>
@ -7,11 +7,35 @@
<button class="page-turn-button">Prev</button> <button class="page-turn-button">Prev</button>
<button class="page-turn-button">Next</button> <button class="page-turn-button">Next</button>
</div> </div>
<div ref="dataTableContainer"></div> <div>
<DataTable :value="data">
<Column
v-for="col in columns"
:key="col.fieldName"
:field="col.fieldName"
:header="col.label"
>
<template #body="slotProps">
<template v-if="col.type === 'status'">
<Badge
:value="slotProps.data[col.fieldName]"
:severity="getBadgeColor(slotProps.data[col.fieldName])"
:size="large"
/>
</template>
<template v-else>
{{ slotProps.data[col.fieldName] }}
</template>
</template>
</Column>
</DataTable>
</div>
</template> </template>
<script setup> <script setup>
import { defineProps, ref, onMounted } from "vue"; import { defineProps } from "vue";
const dataTableContainer = ref(null); import DataTable from "primevue/datatable";
import Column from "primevue/column";
import Badge from "primevue/badge";
const props = defineProps({ const props = defineProps({
columns: { columns: {
type: Array, type: Array,
@ -22,22 +46,30 @@ const props = defineProps({
required: true, required: true,
}, },
}); });
const getBadgeColor = (status) => {
onMounted(() => { console.log("DEBUG: - getBadgeColor status", status);
console.log(dataTableContainer); switch (status?.toLowerCase()) {
if (!dataTableContainer.value) { case "completed":
console.error("Datatable container not found!"); return "success"; // green
return; case "in progress":
case "warn":
return "warning"; // yellow
case "not started":
return "danger"; // red
default:
return "info"; // blue fallback
} }
};
console.log("DEBUG: - DataTable props.columns", props.columns);
console.log("DEBUG: - DataTable props.data", props.data);
const columnsList = props.columns.map((col) => col.label); // const columnsList = props.columns.map((col) => col.label);
const dataList = props.data.map((row) => props.columns.map((col) => row[col.fieldName] || "")); // const dataList = props.data.map((row) => props.columns.map((col) => row[col.fieldName] || ""));
// Pass the actual DOM element // Pass the actual DOM element
new frappe.DataTable(dataTableContainer.value, { // new frappe.DataTable(dataTableContainer.value, {
columns: columnsList, // columns: columnsList,
data: dataList, // data: dataList,
}); // });
});
</script> </script>
<style lang=""></style> <style lang=""></style>

View File

@ -9,7 +9,7 @@
Add Add
</button> </button>
</div> </div>
<DataTable v-if="tableData.length > 0" :data="tableData" :columns="columns" /> <DataTable :data="tableData" :columns="columns" />
</div> </div>
</template> </template>
<script setup> <script setup>
@ -23,20 +23,25 @@ const onClick = () => {
frappe.new_doc("Customer"); frappe.new_doc("Customer");
}; };
const searchFields = { fields: ["full_name", "address", "email_id", "phone"] };
const columns = [ const columns = [
{ label: "Name", fieldName: "full_name" }, { label: "Name", fieldName: "fullName", type: "text" },
{ label: "Location", fieldName: "address" }, { label: "Appt. Scheduled", fieldName: "appointmentScheduled", type: "status" },
{ label: "Type", fieldName: "contact_type" }, { label: "Estimate Sent", fieldName: "estimateSent", type: "status" },
{ label: "Contact", fieldName: "full_name" }, { label: "Payment Received", fieldName: "paymentReceived", type: "status" },
{ label: "Email", fieldName: "email_id" }, { label: "Job Status", fieldName: "jobStatus", type: "status" },
{ label: "Phone", fieldName: "phone" },
]; ];
onMounted(async () => { onMounted(async () => {
if (tableData.value.length > 0) {
return;
}
let data = await Api.getClientDetails(); let data = await Api.getClientDetails();
// data = data.map((item) => [
console.log(data); // item.customer["customer_name"] || "",
console.log(tableData.value); // item.address["appointment_scheduled"] || "",
// item.address["estimate_sent"] || "",
// item.address["payment_received"] || "",
// item.address["job_status"] || "",
// ]);
tableData.value = data; tableData.value = data;
}); });
</script> </script>

View File

@ -2,5 +2,6 @@ import { createApp } from "vue";
import "./style.css"; import "./style.css";
import App from "./App.vue"; import App from "./App.vue";
import router from "./router"; import router from "./router";
import PrimeVue from "primevue/config";
createApp(App).use(router).mount("#custom-ui-app"); createApp(App).use(router).use(PrimeVue).mount("#custom-ui-app");

47
frontend/src/utils.js Normal file
View File

@ -0,0 +1,47 @@
class DataUtils {
// static buildClientData(clients) {
// const address = `${client["address"]["address_line_1"] || ""} ${client["address"]["address_line_2"] || ""} ${client["address"]["city"] || ""} ${client["address"]["state"] || ""}`.trim();
// const clientName = `${client["customer"]["customer_name"] || "N/A"} ${address}`;
// return clients.map((client) => [clientName, client.]
// }
static dummyClientData = [
{
fullName: "John Doe 123 Lane Dr Cityville, MN",
appointmentScheduled: "completed",
estimateSent: "pending",
paymentReceived: "not started",
jobStatus: "not started",
},
{
fullName: "Jane Smith 456 Oak St Townsville, CA",
appointmentScheduled: "pending",
estimateSent: "not started",
paymentReceived: "not started",
jobStatus: "not started",
},
{
fullName: "Mike Johnson 789 Pine Rd Villagetown, TX",
appointmentScheduled: "completed",
estimateSent: "completed",
paymentReceived: "pending",
jobStatus: "in progress",
},
{
fullName: "Emily Davis 321 Maple Ave Hamlet, FL",
appointmentScheduled: "not started",
estimateSent: "not started",
paymentReceived: "not started",
jobStatus: "not started",
},
{
fullName: "David Wilson 654 Cedar Blvd Borough, NY",
appointmentScheduled: "completed",
estimateSent: "completed",
paymentReceived: "completed",
jobStatus: "completed",
},
];
}
export default DataUtils;