CPE Dashboard using Vue.js

<!DOCTYPE html>
<html lang="en">


<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Program Delivery Dashboard</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
    <style>
        body {
            margin: 0;
            font-family: Arial, sans-serif;
            background-color: #f0f0f0;
        }


        .header {
            border: 2px solid #080909;
            padding: 5px 10px;
            border-radius: 0;
            background-color: #a8c4e3;
            color: #050101;
            font-family: Arial, Helvetica, sans-serif;
            box-shadow: 5px 5px 5px grey;
            text-align: center;
        }


        /* Styled Date Picker */
        .date-picker-container {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }


        .date-picker-label {
            margin-right: 10px;
            margin-left: 10px;
            font-size: 16px;
            color: #010101;
        }


        .date-picker-input {
            padding: 10px;
            margin: 5px;
            border: 2px solid #010101;
            border-radius: 5px;
            font-size: 16px;
            outline: none;
        }


        .button-row {
            margin-top: 10px;
            border-radius: 0;
            padding: 3px;
            background-color: #81b9f2;
            box-shadow: 5px 5px 5px grey;
            display: flex;
        }


        .button-container {
            display: flex;
            flex-wrap: wrap;
            width: 100%;
            justify-content: center;
            /* Align items to the center */
        }


        .button {
            display: inline-block;
            padding: 5px;
            /* Reduced padding */
            margin: 5px;
            width: 100px;
            border: 2px solid #010101;
            border-radius: 5px;
            background-color: #fafbfc;
            color: #010000;
            cursor: pointer;
            transition: background-color 0.3s, color 0.3s;
            font-size: 14px;
            /* Reduced font size */
        }


        .button:hover {
            background-color: #81b9f2;
            color: white;
        }


        .selected {
            background-color: #81b9f2;
            color: white;
        }


        h2 span {
            padding: 5px 10px;
            border-radius: 0;
            background-color: #f9fafc;
            color: #050101;
            font-family: Arial, Helvetica, sans-serif;
            box-shadow: 5px 5px 5px grey;
        }


        .card {
            background-color: #fff;
            border: 1px solid #ccc;
            border-radius: 5px;
            padding: 10px;
            text-align: center;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
        }


        .card-container {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 5px;
            margin-top: 10px;
        }


        .costKpi {
            background-color: #7bcf90;
        }


        .teamKpi {
            background-color: #d0e6a8;
        }


        .label {
            margin-bottom: 10px;
            font-size: 15px;
            font-family: Arial, Helvetica, sans-serif;
            text-align: left;
        }


        .value {
            font-weight: bold;
            font-size: 20px;
        }


        .submit-button {
            text-align: center;
            margin-top: 10px;
        }


        .submit-button button {
            padding: 10px 20px;
            background-color: #81b9f2;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s;
            font-weight: bold;
            width: 200px
        }


        .submit-button button:hover {
            background-color: #5a8cb2;
        }
    </style>
</head>
<!-- Body section -->


<body>
    <div id="app">
        <div class="header">
            <h1>{{ pageTitle }}</h1>
        </div>
        <!-- Date Picker -->
        <div class="button-row" style="justify-content: center;">
            <div class="date-picker-container">
                <span class="date-picker-label">From Date:</span>
                <input type="date" v-model="selectedFromDate" class="date-picker-input">
            </div>
            <div class="date-picker-container">
                <span class="date-picker-label">To Date:</span>
                <input type="date" v-model="selectedToDate" class="date-picker-input">
            </div>
        </div>
        <div class="button-row" style="justify-content: center;">
            <div class="button-container">
                <button v-for="(otherFilter, index) in otherFilter" :key="index"
                    :class="{ 'button': true, 'selected': isOtherFilterSelected(index) }"
                    @click="selectOtherFilters(index)">{{ otherFilter.key }}</button>
            </div>
        </div>
        <!-- Cost Center Buttons -->
        <div class="button-row">
            <div class="button-container">
                <div class="button-container">
                    <button class="button selectAllCostCenterButton" @click="selectAllCostCenter">Select All</button>
                    <button class="button selectAllCostCenterButton" @click="unselectAllCostCenter">Unselect
                        All</button>
                </div>
                <div class="button-container"><button v-for="(costCenter, index) in costCenter" :key="index"
                        :class="{ 'button': true, 'selected': isCostCenterSelected(costCenter.id) }"
                        @click="selectCostCenter(costCenter.id)">{{ costCenter.name }}</button></div>
            </div>
        </div>
        <div class="submit-button">
            <button class="submit-button" @click="submitButtonAction">Submit</button>
        </div>
        <div>
            <div>
                <h2><span>Cost KPIs</span></h2>
            </div>
            <div class="card-container">
                <div v-for="(item, index) in costKPIs" :key="index" class="card costKpi">
                    <div class="label">{{ item.label }}</div>
                    <div class="value">{{ item.value }}</div>
                </div>
            </div>
        </div>
        <div>
            <div>
                <h2><span>Team KPIs</span></h2>
            </div>
            <div class="card-container">
                <div v-for="(item, index) in teamKPIs" :key="index" class="card teamKpi">
                    <div class="label">{{ item.label }}</div>
                    <div class="value">{{ item.value }}</div>
                </div>
            </div>
        </div>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                pageTitle: 'Program Delivery Dashboard',
                selectedFromDate: null,
                selectedToDate: null,
                costCenter: [],
                selectedCostCenters: [],
                otherFilter: [{ key: "Billable", isSelected: false }, { key: "Buffer", isSelected: false }],
                selectedOtherFilters: [0, 1],
                costKPIs: [{ label: "Actual Revenue ($)", value: "" }, { label: "Acsia Cost ($)", value: "" }, { label: "Acsia Direct Cost ($)", value: "" }, { label: "Expected Revenue ($)", value: "" },
                { label: "Avg Actual RPE/Hr ($)", value: "" }, { label: "Avg CPE/Hr ($)", value: "" }, { label: "Avg Direct CPE/Hr ($)", value: "" }, { label: "Avg Expected RPE/Hr ($)", value: "" }, { label: "EBITA % [Project Margin]", value: "" },
                { label: "Margin ($)", value: "" }, { label: "Gross Margin ($)", value: "" }, { label: "Revenue Leakage ($)", value: "" }],
                teamKPIs: [{ label: "Available Hours", value: "" }, { label: "Billed Hours", value: "" }, { label: "RESOURCE UTILIZATION (%)", value: "" }, { label: "Resource Count", value: "" },
                { label: "Billable", value: "" }, { label: "Buffer", value: "" }],
                companyUrl: "https://9267067-rp.app.netsuite.com/",
                scriptId: 'customscript_jj_sl_cpe_dashboard_atpl577',
                deploymentId: 'customdeploy_jj_sl_cpe_dashboard_atpl577',
                unwrapInEscapedBody: (data) => {
                    return JSON.parse(decodeURIComponent(data));
                },
            },
            mounted() {
                this.getCostCenters()
                this.get
            },
            methods: {
                selectAllCostCenter() {
                    this.selectedCostCenters = this.costCenter.map(costCenter => costCenter.id);
                },
                selectCostCenter(id) {
                    if (this.selectedCostCenters.includes(id)) {
                        // Deselect month
                        this.selectedCostCenters.splice(this.selectedCostCenters.indexOf(id), 1);
                    } else {
                        // Select month
                        this.selectedCostCenters.push(id);
                    }
                },
                isCostCenterSelected(id) {
                    return this.selectedCostCenters.includes(id);
                },
                unselectAllCostCenter() {
                    this.selectedCostCenters = []
                },
                selectOtherFilters(index) {
                    if (this.selectedOtherFilters.includes(index)) {
                        // Deselect month
                        this.selectedOtherFilters.splice(this.selectedOtherFilters.indexOf(index), 1);
                    } else {
                        // Select month
                        this.selectedOtherFilters.push(index);
                    }
                },
                isOtherFilterSelected(index) {
                    return this.selectedOtherFilters.includes(index);
                },
                generateEndPoint(apiType) {
                    return `${this.companyUrl}/app/site/hosting/scriptlet.nl?script=${this.scriptId}&deploy=${this.deploymentId}&apiType=${apiType}`
                },
                async getCostCenters() {
                    let endPoint = this.generateEndPoint('listCostCenters')
                    let response = await fetch(endPoint, {
                        method: 'GET',
                        headers: {
                            'Content-Type': 'application/json',
                            'Access-Control-Allow-Origin': '*'
                        },
                    })
                    let responseData = await response.json();
                    this.costCenter = responseData.data.fields;
                },
                async submitButtonAction() {
                    let filters = {};
                    filters.fromDate = this.selectedFromDate || '';
                    filters.toDate = this.selectedToDate || '';
                    filters.costCenters = this.selectedCostCenters.length > 0 ? this.selectedCostCenters.join(',') : '';
                    filters.otherFilters = this.selectedOtherFilters.length > 0 ? this.selectedOtherFilters.map(index => this.otherFilter[index].key).join(',') : '';


                    let endPoint = this.generateEndPoint('fetchData');


                    let response = await fetch(endPoint, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Access-Control-Allow-Origin': '*'
                        },
                        body: JSON.stringify(filters)
                    });
                    let responseData = await response.json();


                    // Set values for cost KPIs
                    this.costKPIs.forEach(item => {
                        const data = responseData.data.fields.find(obj => obj.label === item.label);
                        if (data) {
                            item.value = data.value;
                        }
                    });
                    // Set values for team KPIs
                    this.teamKPIs.forEach(item => {
                        const data = responseData.data.fields.find(obj => obj.label === item.label);
                        if (data) {
                            item.value = data.value;
                        }
                    });
                }
            }
        });
    </script>
</body>


</html>

Leave a comment

Your email address will not be published. Required fields are marked *