Jump to content

Button Variable of foreach loop being set correct but when passed to javascript it remains the value of the last button variable in foreach loop


Recommended Posts

Ok here goes hope i can explain this correctly. 

Im building an internal quoting system

 

THE PROBLEM:

image.thumb.png.34b380abf030cd1147e150c422d58b7f.png

These buttons 1, 2, and 3 when code is inspected all have the correct quote_item_id

image.thumb.png.593679fea11721a2c2b197d0dd8401cb.png

image.thumb.png.e9702d8289390a9b91154fa60de43f1c.png

However when you click on any change quantity the javascript brings up the popup with the very last line items quote_item_id every time.

 

image.png.b26cbcbb694cdd4f5d094030cf4ca336.png

THE CODE: This bit of code is whats doing the work 

// Loop
if (count($quoteItems) > 0) {
	echo "<!-- Entering quoteItems loop -->";
    foreach ($quoteItems as $item) {
		echo "<!-- Looping item: quote_item_id = {$item['quote_item_id']} -->";
        echo "<!-- DEBUG quote_item_id: {$item['quote_item_id']} -->";  // 🔍 Debug line
        $isCustom = $item['is_custom_item'] ?? 0;
        $productName = $isCustom ? 'Custom Item' : ($item['product_name'] ?? '—');
        $description = $isCustom ? ($item['custom_description'] ?? '—') : ($item['description'] ?? '—');

        echo "<tr>";
        echo "<td>" . htmlspecialchars($productName) . "</td>";
        echo "<td>" . htmlspecialchars($description) . "</td>";

        // Quantity with 🛠 button
		$quoteItemId = (int)$item['quote_item_id'];
        echo "<td>" . htmlspecialchars($item['quantity']) . "";
		 
		echo "<button 
		type=\"button\" 
		onclick=\"openEditQuantityPopup(" . (int)$item['quote_item_id'] . ", " . (int)$quoteId . ")\" 
		title=\"Edit Quantity\" 
		style=\"border: none; background: none; cursor: pointer; font-size: 14px;\">
		🛠
		</button>"; 
		echo "</td>";

        echo "<td>" . number_format((float)$item['WSExPerUnit'], 2) . "</td>";
        echo "<td>" . number_format((float)$item['SellExPerUnit'], 2) . "</td>";
        echo "<td>" . number_format((float)$item['SellTotalEx'], 2) . "</td>";
        echo "<td>" . number_format((float)$item['SellTotalInc'], 2) . "</td>";
        echo "<td>" . number_format((float)$item['GSTAmount'], 2) . "</td>";

        // Delete button
        echo "<td style='text-align: center;'>
            <form method='POST' action='Quotes.php?action=edit_quote&id=" . (int)$quoteId . "' 
                  onsubmit=\"return confirm('Are you sure you want to delete this item?');\" 
                  style='display:inline;'>
                <input type='hidden' name='delete_item_id' value='" . (int)$item['quote_item_id'] . "'>
                <button type='submit' style='border:none; background:none; color:red; font-size:16px;'></button>
            </form>
        </td>";
        
        echo "</tr>";
    }
} else {
    echo "<tr><td colspan='9' style='text-align:center;'><em>No items added yet.</em></td></tr>";
}

And this is the javascript calling the popup window
 

function openEditQuantityPopup(quoteItemId, quoteId) {
    const width = 400;
    const height = 200;

    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

    const screenWidth = window.innerWidth || document.documentElement.clientWidth || screen.width;
    const screenHeight = window.innerHeight || document.documentElement.clientHeight || screen.height;

    const left = dualScreenLeft + (screenWidth - width) / 2;
    const top = dualScreenTop + (screenHeight - height) / 2;

    window.open(
        `Quotes/Edit_Quote_Quantity.php?quote_item_id=${quoteItemId}&quote_id=${quoteId}`,
        "EditQuoteQuantity",
        "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left + ",resizable=no,scrollbars=no"
    );
}

and this is the Edit_Quote_Quantity.php that run when button is clicked

<?php
var_dump($_GET);
include '../Functions/db_con.php';

$quoteItemId = $_GET['quote_item_id'] ?? null;
$quoteId = $_GET['quote_id'] ?? null;

if (!$quoteItemId || !$quoteId) {
    echo "Missing parameters.";
    exit;
}

// Get current quantity
$stmt = $pdo->prepare("SELECT quantity FROM QuoteItems WHERE quote_item_id = ?");
$stmt->execute([$quoteItemId]);
$item = $stmt->fetch(PDO::FETCH_ASSOC);

$currentQty = $item['quantity'] ?? 1;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $newQty = (int)$_POST['quantity'];

    // Update quantity
    $update = $pdo->prepare("UPDATE QuoteItems SET quantity = ? WHERE quote_item_id = ?");
    $update->execute([$newQty, $quoteItemId]);

    echo "<script>window.opener.location.reload(); window.close();</script>";
    exit;
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>Edit Quantity</title>
</head>
<body style="font-family: Arial; padding: 20px;">
    <h3>Edit Quantity</h3>
    <form method="POST">
        <label>New Quantity:</label><br>
        <input type="number" name="quantity" value="<?= htmlspecialchars($currentQty) ?>" min="1" required><br><br>
        <button type="submit">Update</button>
    </form>
</body>
</html>

 

The process actually works however it always changes the quantity to the last line item called up in the foreach loop. Been racking my brains for a day on this one trying to work it out.

a test page works for me (uses the correct quoteItemId matching the clicked button, both in the javascript and in the php code) in chrome, edge, and firefox, but i don't have all the code on your page. the only changes i made to the //loop code is to add a <table> tag before it and comment out the 5 lines with number_format() calls, since i didn't want to make up fake data to loop over for these. do you have some event listener for 'buttons' that could be affecting this? this is acting like some broken markup is causing all those buttons to call the last openEditQuantityPopup(...), instead of the correct one or all the buttons are being clicked and you are seeing the end result from the last such operation. i would console.log the quoteItemId value inside the openEditQuantityPopup() faction, so that you can see how many times it gets called, and with what value as an input.

in the end, you will need to post all the code on that page that's necessary to reproduce the problem.

Edited by mac_gyver
<?php

function renderQuoteTopButtons() {
    echo <<<HTML
    <div style="margin-bottom: 20px;">
        <button onclick="startNewQuote()">📝 New Quote</button>
        <button onclick="loadTemplateQuote()">📄 Quote from Template</button>
        <button onclick="cloneQuote()">📋 Clone Quote</button>
    </div>
    HTML;
}

function renderNewQuoteFormWithClientSearch() {
    echo <<<HTML
    <div id="newQuoteForm" style="display: block; margin-top: 20px;">
        <h3>New Quote Details</h3>

        <form method="POST" action="Quotes.php?action=create_quote">
            <label for="clientSearch">Search Customer:</label><br>
            <input type="text" id="clientSearch" name="clientSearch" oninput="getSuggestions(this.value)" autocomplete="off" required>
            <input type="hidden" name="selectedCustomerId" id="selectedCustomerId">
            <div id="suggestions"></div><br>

            <label for="quoteTitle">Quote Title:</label><br>
            <input type="text" id="quoteTitle" name="quoteTitle" required><br><br>

            <label for="quoteDate">Quote Date:</label><br>
            <input type="date" id="quoteDate" name="quoteDate" required><br><br>

            <label for="quoteNotes">Notes (Optional):</label><br>
            <textarea id="quoteNotes" name="quoteNotes" rows="4" cols="50"></textarea><br><br>

            <button type="submit">Create Quote</button>
        </form>
    </div>
HTML;

    // JavaScript for showing the form and handling customer selection
    echo <<<JS
<script>
function startNewQuote() {
    document.getElementById('newQuoteForm').style.display = 'block';
}

function getSuggestions(query) {
    if (query.length === 0) {
        document.getElementById("suggestions").innerHTML = "";
        return;
    }

    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            document.getElementById("suggestions").innerHTML = this.responseText;
        }
    };
    xhttp.open("GET", "Functions/get_customer_suggestions.php?q=" + encodeURIComponent(query), true);
    xhttp.send();
}

function selectSuggestion(id, name) {
    document.getElementById("clientSearch").value = name;
    document.getElementById("selectedCustomerId").value = id;
    document.getElementById("suggestions").innerHTML = "";
}
</script>

JS;
}
function renderEditQuoteForm($pdo, $quoteId) {
    // Fetch quote and customer data
    $stmt = $pdo->prepare("SELECT q.*, c.CompanyName FROM Quote q JOIN Customer c ON q.CustomerID = c.CustomerID WHERE q.QuoteID = ?");
    $stmt->execute([$quoteId]);
    $quote = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$quote) {
        echo "<p> Quote not found.</p>";
        return;
    }
// 💰 Calculate total profit and margin
$totalProfit = $quote['QuoteEXTotal'] - $quote['QuoteOurBuytotalEx'];
$profitMargin = $quote['QuoteEXTotal'] > 0 ? round(($totalProfit / $quote['QuoteEXTotal']) * 100, 2) : 0;

    // Fetch contacts for dropdown
    $contacts = $pdo->prepare("SELECT ContactID, FirstName, LastName FROM Contact WHERE CustomerID = ?");
    $contacts->execute([$quote['CustomerID']]);

    // Fetch sales people
    $techs = $pdo->query("SELECT TechnicianID, FirstName, LastName FROM Technician")->fetchAll(PDO::FETCH_ASSOC);

    // Fetch statuses
    $statuses = $pdo->query("SELECT QuoteStatusID, StatusDescription FROM QuoteStatus")->fetchAll(PDO::FETCH_ASSOC);
	echo "<br><br>";
    echo "<form method='POST' action='Quotes.php?action=update_quote&id={$quoteId}'>";

    // 🌟 Header layout (3 columns)
    echo <<<HTML
<br><br>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
    <!-- Customer name (left) -->
    <div style="flex: 1; text-align: left;">
        <strong>Customer:</strong> {$quote['CompanyName']}
    </div>

    <!-- Quote Title (center-left) --> 
    <div style="flex: 1; text-align: center;">
        <span>{$quote['QuoteTitle']}</span>
        <button type="button" onclick="openQuoteTitlePopup({$quote['QuoteID']})" style="border: none; background: none; cursor: pointer;">✏️</button>
    </div>

    <!-- Contact (center-right) -->
    <div style="flex: 1; text-align: center;">
        <label><strong>Contact:</strong></label>
        <span>
HTML;

    // Close heredoc to insert PHP logic
    $contactName = '';
    $contactStmt = $pdo->prepare("SELECT FirstName, LastName FROM Contact WHERE ContactID = ?");
    $contactStmt->execute([$quote['QuotecontactID']]);
    if ($contactRow = $contactStmt->fetch(PDO::FETCH_ASSOC)) {
        $contactName = htmlspecialchars($contactRow['FirstName'] . ' ' . $contactRow['LastName']);
    }
    echo $contactName ?: "<em>No Contact Selected</em>";

    echo " <button type='button' onclick='openContactEditPopup({$quoteId})' title='Edit Contact' style='margin-left: 6px; font-size: 14px; border: none; background: none; cursor: pointer;'>👤</button>";
     echo "</span><br><label><strong>Sales Person:</strong></label> <span>";

    // Insert PHP logic for Sales Person
    $salesPersonName = '';
    $salesStmt = $pdo->prepare("SELECT FirstName, LastName FROM Technician WHERE TechnicianID = ?");
    $salesStmt->execute([$quote['SalesPerson']]);
    if ($salesRow = $salesStmt->fetch(PDO::FETCH_ASSOC)) {
        $salesPersonName = htmlspecialchars($salesRow['FirstName'] . ' ' . $salesRow['LastName']);
    }
    echo $salesPersonName ?: "<em>Not Assigned</em>";
    echo " <button type='button' onclick='openSalesPersonEditPopup({$quoteId})' title='Edit Sales Person' style='margin-left: 6px; font-size: 14px; border: none; background: none; cursor: pointer;'>👤</button>";

echo "</span>";
	
// Resume heredoc
echo <<<HTML
        </span>
   
HTML;



$escapedNotes = htmlspecialchars($quote['Notes']);

// Close previous heredoc and resume HTML
echo <<<HTML
        </select>
    </div>

    <!-- Quote ID and Date Created (right) -->
    <div style="flex: 1; text-align: right;">
        <strong>Quote #{$quote['QuoteID']}</strong><br>
        <small>
            <strong>Date Created:</strong> {$quote['DateCreated']}
            <button type="button" onclick="openDateEditPopup({$quote['QuoteID']})" style="border: none; background: none; cursor: pointer;">
                📅
            </button>
        </small>
    

    <div style="margin-top: 6px;">
        <small>
            <strong>Quote Expiry Date:</strong> {$quote['QuoteExpireyDate']}
            <button type="button" onclick="openExpiryEditPopup({$quote['QuoteID']})" style="border: none; background: none; cursor: pointer;">
                📅
            </button>
        </small>
    </div>
        <div style="margin-top: 8px;">
            <label style="font-size: 13px;"><strong>Quote Notes:</strong></label>
            <button type="button" onclick="openNotesPopup({$quote['QuoteID']})" title="View & Edit Notes" style="border: none; background: none; cursor: pointer;">🔍</button>
        </div>
		<!-- Hidden field to keep existing notes in form -->
<input type="hidden" name="Notes" value="{$escapedNotes}">
HTML;


//  Determine current status text
$currentStatusText = '';
foreach ($statuses as $status) {
    if ($status['QuoteStatusID'] == $quote['StatusID']) {
        $currentStatusText = htmlspecialchars($status['StatusDescription']);
        break;
    }
}

//  Output status row
echo <<<HTML
        <div style="margin-top: 8px;">
            <label style="font-size: 13px;"><strong>Status:</strong></label>
            <span style="margin-left: 6px; font-weight: bold;">{$currentStatusText}</span>
            <button type="button" onclick="openStatusEditPopup({$quote['QuoteID']})" title="Edit Status" style="border: none; background: none; cursor: pointer;">✏️</button>
        </div>
    </div>
</div>
HTML;


// 🔍 Quote Notes with popup button
//$escapedNotes = htmlspecialchars($quote['Notes']);
//echo <<<HTML
//<div style="margin-bottom: 10px;">
//    <label><strong>Quote Notes:</strong></label>
//    <button type="button" onclick="openNotesPopup({$quote['QuoteID']})" title="View & Edit Notes" style="margin-left: 8px; font-size: 16px;">🔍</button>
//</div>
//<!-- Hidden field to keep existing notes in form -->
//<input type="hidden" name="Notes" value="{$escapedNotes}">
//HTML;



  //  echo "</select><br><br>";
// 🧾 Quote Items Header and Add Button
echo <<<HTML
<hr style="margin: 20px 0;">
<div style="display: flex; justify-content: space-between; align-items: center;">
    <h4 style="margin: 0;">Quote Items</h4>
    <button type="button" onclick="openAddItemPopup({$quote['QuoteID']})" title="Add Item" style="font-size: 16px; cursor: pointer;">
         Add Item
    </button>
</div>

<table border="1" cellpadding="6" cellspacing="0" width="100%" style="margin-top: 10px; text-align: left;">
    <thead>
        <tr>
            <th>Product Name</th>
            <th>Description</th>
            <th>Quantity</th>
            <th>WS Ex Per Unit</th>
            <th>Sell Ex Per Unit</th>
            <th>Sell Tot Ex</th>
            <th>Sell Tot Inc</th>
            <th>GST</th>
			<th>Del</th>
        </tr>
    </thead>
    <tbody>
HTML;

// Fetch quote items
// Fetch quote items
$itemsStmt = $pdo->prepare("
    SELECT 
        qi.quote_item_id,
        qi.product_id,
        qi.service_id,
        qi.WSExPerUnit,
        qi.SellExPerUnit,
        qi.SellTotalEx,
        qi.SellTotalInc,
        qi.quantity,
        qi.discount,
        qi.GSTAmount,
        qi.custom_description,
        qi.is_custom_item,
        p.product_name,
        p.description
    FROM QuoteItems qi
    LEFT JOIN Products p ON qi.product_id = p.product_id
    WHERE qi.quote_id = ?
");

$itemsStmt->execute([$quoteId]);
$quoteItems = $itemsStmt->fetchAll(PDO::FETCH_ASSOC);

// Loop
if (count($quoteItems) > 0) {
	echo "<!-- Entering quoteItems loop -->";
    foreach ($quoteItems as $item) {
		echo "<!-- Looping item: quote_item_id = {$item['quote_item_id']} -->";
        echo "<!-- DEBUG quote_item_id: {$item['quote_item_id']} -->";  // 🔍 Debug line
        $isCustom = $item['is_custom_item'] ?? 0;
        $productName = $isCustom ? 'Custom Item' : ($item['product_name'] ?? '—');
        $description = $isCustom ? ($item['custom_description'] ?? '—') : ($item['description'] ?? '—');

        echo "<tr>";
        echo "<td>" . htmlspecialchars($productName) . "</td>";
        echo "<td>" . htmlspecialchars($description) . "</td>";

        // Quantity with 🛠 button
		$quoteItemId = (int)$item['quote_item_id'];
        echo "<td>" . htmlspecialchars($item['quantity']) . "";
		 
		echo "<button 
		type=\"button\" 
		onclick=\"openEditQuantityPopup(" . (int)$item['quote_item_id'] . ", " . (int)$quoteId . ")\" 
		title=\"Edit Quantity\" 
		style=\"border: none; background: none; cursor: pointer; font-size: 14px;\">
		🛠
		</button>"; 
		echo "</td>";

        echo "<td>" . number_format((float)$item['WSExPerUnit'], 2) . "</td>";
        echo "<td>" . number_format((float)$item['SellExPerUnit'], 2) . "</td>";
        echo "<td>" . number_format((float)$item['SellTotalEx'], 2) . "</td>";
        echo "<td>" . number_format((float)$item['SellTotalInc'], 2) . "</td>";
        echo "<td>" . number_format((float)$item['GSTAmount'], 2) . "</td>";

        // Delete button
        echo "<td style='text-align: center;'>
            <form method='POST' action='Quotes.php?action=edit_quote&id=" . (int)$quoteId . "' 
                  onsubmit=\"return confirm('Are you sure you want to delete this item?');\" 
                  style='display:inline;'>
                <input type='hidden' name='delete_item_id' value='" . (int)$item['quote_item_id'] . "'>
                <button type='submit' style='border:none; background:none; color:red; font-size:16px;'></button>
            </form>
        </td>";
        
        echo "</tr>";
    }
} else {
    echo "<tr><td colspan='9' style='text-align:center;'><em>No items added yet.</em></td></tr>";
}




// Resume heredoc
echo <<<HTML
    </tbody>
</table>
HTML;




    // 💰 Totals (read-only)
    echo "<br><label>Ex. Total:</label> {$quote['QuoteEXTotal']}<br>";
    echo "<label>Tax Total:</label> {$quote['QuoteTaxTotal']}<br>";
    echo "<label>Inc. Total:</label> {$quote['QuoteIncTotal']}<br>";
    echo "<label>Our Buy Total (Ex):</label> {$quote['QuoteOurBuytotalEx']}<br><br>";

	//echo "<button type='button' onclick='openUpdateTotalsPopup({$quoteId})'>📊 Update Totals</button>";
	echo "<button type=\"button\" onclick=\"openUpdateTotalsPopup({$quoteId})\">📊 Update Totals</button>";
	echo "<br><br><label><strong>Total Profit (Ex GST):</strong></label> \$" . number_format($totalProfit, 2) . "<br>";
	echo "<label><strong>Profit Margin:</strong></label> {$profitMargin}%<br><br>";

    echo "</form>";
	
	echo <<<JS
<script>
function openNotesPopup(quoteId) {
    const width = 800;
    const height = 400;

    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

    const screenWidth = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
    const screenHeight = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

    const left = dualScreenLeft + (screenWidth - width) / 2;
    const top = dualScreenTop + (screenHeight - height) / 2;

    window.open(
        "Quotes/Quote_Notes.php?id=" + quoteId,
        "QuoteNotes",
        "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left + ",resizable=yes,scrollbars=yes"
    );
}

function openQuoteTitlePopup(quoteId) {
    const width = 400;
    const height = 200;

    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

    const screenWidth = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
    const screenHeight = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

    const left = dualScreenLeft + (screenWidth - width) / 2;
    const top = dualScreenTop + (screenHeight - height) / 2;

    window.open(
        "Quotes/Edit_Quote_Title.php?id=" + quoteId,
        "EditQuoteTitle",
        "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left + ",resizable=no,scrollbars=no"
    );
}

function openDateEditPopup(quoteId) {
    const width = 400;
    const height = 200;

    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

    const screenWidth = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
    const screenHeight = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

    const left = dualScreenLeft + (screenWidth - width) / 2;
    const top = dualScreenTop + (screenHeight - height) / 2;

    window.open(
        "Quotes/Edit_Quote_Date.php?id=" + quoteId,
        "EditQuoteDate",
        "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left + ",resizable=no,scrollbars=no"
    );
}
function openStatusEditPopup(quoteId) {
    const width = 400;
    const height = 250;

    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

    const screenWidth = window.innerWidth || document.documentElement.clientWidth || screen.width;
    const screenHeight = window.innerHeight || document.documentElement.clientHeight || screen.height;

    const left = dualScreenLeft + (screenWidth - width) / 2;
    const top = dualScreenTop + (screenHeight - height) / 2;

    window.open(
        "Quotes/Edit_Quote_Status.php?id=" + quoteId,
        "EditQuoteStatus",
        "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left + ",resizable=no,scrollbars=no"
    );
}

function openExpiryEditPopup(quoteId) {
    const width = 400;
    const height = 200;

    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

    const screenWidth = window.innerWidth || document.documentElement.clientWidth || screen.width;
    const screenHeight = window.innerHeight || document.documentElement.clientHeight || screen.height;

    const left = dualScreenLeft + (screenWidth - width) / 2;
    const top = dualScreenTop + (screenHeight - height) / 2;

    window.open(
        "Quotes/Edit_Quote_Expiry.php?id=" + quoteId,
        "EditQuoteExpiry",
        "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left + ",resizable=no,scrollbars=no"
    );
}

function openContactEditPopup(quoteId) {
    const width = 400;
    const height = 200;

    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

    const screenWidth = window.innerWidth || document.documentElement.clientWidth || screen.width;
    const screenHeight = window.innerHeight || document.documentElement.clientHeight || screen.height;

    const left = dualScreenLeft + (screenWidth - width) / 2;
    const top = dualScreenTop + (screenHeight - height) / 2;

    window.open(
        "Quotes/Edit_Quote_Contact.php?id=" + quoteId,
        "EditQuoteContact",
        "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left + ",resizable=no,scrollbars=no"
    );
}

function openSalesPersonEditPopup(quoteId) {
    const width = 400;
    const height = 200;

    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

    const screenWidth = window.innerWidth || document.documentElement.clientWidth || screen.width;
    const screenHeight = window.innerHeight || document.documentElement.clientHeight || screen.height;

    const left = dualScreenLeft + (screenWidth - width) / 2;
    const top = dualScreenTop + (screenHeight - height) / 2;

    window.open(
        "Quotes/Edit_Quote_SalesPerson.php?id=" + quoteId,
        "EditQuoteSalesPerson",
        "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left + ",resizable=no,scrollbars=no"
    );
}

function openAddItemPopup(quoteId) {
    const width = 600;
    const height = 400;
    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;
    const screenWidth = window.innerWidth || document.documentElement.clientWidth || screen.width;
    const screenHeight = window.innerHeight || document.documentElement.clientHeight || screen.height;
    const left = dualScreenLeft + (screenWidth - width) / 2;
    const top = dualScreenTop + (screenHeight - height) / 2;

    window.open(
        "Quotes/Add_Quote_Item.php?quoteId=" + quoteId,
        "AddQuoteItem",
        "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left + ",resizable=no,scrollbars=no"
    );
}

function openUpdateTotalsPopup(quoteId) {
    const width = 400;
    const height = 200;
    const left = (window.innerWidth - width) / 2;
    const top = (window.innerHeight - height) / 2;

    window.open(
        `Quotes/Update_Quote_Totals.php?quoteId=${quoteId}`,
        'UpdateQuoteTotals',
        `width=${width},height=${height},top=${top},left=${left},resizable=no,scrollbars=no`
    );
}
function openEditQuantityPopup(quoteItemId, quoteId) {
    const width = 400;
    const height = 200;

    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

    const screenWidth = window.innerWidth || document.documentElement.clientWidth || screen.width;
    const screenHeight = window.innerHeight || document.documentElement.clientHeight || screen.height;

    const left = dualScreenLeft + (screenWidth - width) / 2;
    const top = dualScreenTop + (screenHeight - height) / 2;

    window.open(
        `Quotes/Edit_Quote_Quantity.php?quote_item_id=${quoteItemId}&quote_id=${quoteId}`,
        "EditQuoteQuantity",
        "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left + ",resizable=no,scrollbars=no"
    );
}


</script>

JS;

}

?>

This is the full Quote_Functions.php code

and this is the Quotes.php below that calls the functions.

<?php 
//ini_set('display_errors', 1);
//ini_set('display_startup_errors', 1);
//error_reporting(E_ALL);
session_start();

// Check if the user is logged in
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
    header("Location: /login.php");
    exit();
}

// Include necessary files
include 'Functions/Common_Functions.php';
include 'Functions/Quote_Functions.php';
include 'Functions/db_con.php';
include 'Functions/Button_Quotes.php'; // Left menu buttons

//  Handle Quote Creation BEFORE output
//  Handle Quote Creation Before Output
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['action']) && $_GET['action'] === 'create_quote') {
    $customerId = $_POST['selectedCustomerId'] ?? null;
    $quoteTitle = $_POST['quoteTitle'] ?? '';
    $quoteDate = $_POST['quoteDate'] ?? '';
    $quoteNotes = $_POST['quoteNotes'] ?? '';

    if ($customerId && $quoteTitle && $quoteDate) {
	$stmt = $pdo->prepare("INSERT INTO Quote (CustomerID, QuoteTitle, Notes, DateCreated, StatusID, QuoteEXTotal, QuoteIncTotal, QuoteTaxTotal, QuoteOurBuytotalEx) 
                       VALUES (?, ?, ?, ?, ?, 0.00, 0.00, 0.00, 0.00)");
	$stmt->execute([$customerId, $quoteTitle, $quoteNotes, $quoteDate, 1]);



        $newQuoteId = $pdo->lastInsertId();

        header("Location: Quotes.php?action=edit_quote&id=" . $newQuoteId);
        exit();
    } else {
        echo " Missing required data.";
        exit();
    }
}

//  Display main menu
func_header();
menu_items();

//  Begin layout
echo "<div class='main-container'>";

//  Left-side menu
echo "<div class='side-menu'>";
echo "<h4 style='color: white; text-align: center;'>Quotes</h4>";
renderQuotesButtons();
echo "</div>";

//  Right-side content
echo "<div class='right-content'>";

//  Routing by action
if (isset($_GET['action'])) {
    switch ($_GET['action']) {
        case 'new_quote':
            echo "<h2 style='text-align: left;'>Create New Quote</h2>";
            renderQuoteTopButtons();
            renderNewQuoteFormWithClientSearch();
            break;

        case 'all_quotes':
            echo "<h2 style='text-align: left;'>All Quotes</h2>";
            break;

        case 'pending_quotes':
            echo "<h2 style='text-align: left;'>Pending Quotes</h2>";
            break;

        case 'approved_quotes':
            echo "<h2 style='text-align: left;'>Approved Quotes</h2>";
            break;

        case 'rejected_quotes':
            echo "<h2 style='text-align: left;'>Rejected Quotes</h2>";
            break;

        case 'expired_quotes':
            echo "<h2 style='text-align: left;'>Expired Quotes</h2>";
            break;

        case 'draft_quotes':
            echo "<h2 style='text-align: left;'>Draft Quotes</h2>";
            break;

        case 'converted_quotes':
            echo "<h2 style='text-align: left;'>Converted Quotes</h2>";
            break;

        case 'search_quotes':
            echo "<h2 style='text-align: left;'>Search Quotes</h2>";
            break;

        case 'customer_quotes':
            echo "<h2 style='text-align: left;'>Customer Quotes</h2>";
            break;

        case 'quote_reports':
            echo "<h2 style='text-align: left;'>Quote Reports</h2>";
            break;

        case 'quote_settings':
            echo "<h2 style='text-align: left;'>Quote Settings</h2>";

            echo '
            <table border="1">
                <tr><th>Feature</th><th>Action</th></tr>
                <tr>
                    <td>Import/Update Products</td>
                    <td><button id="importProducts">Import</button> <span id="syncStatus"></span></td>
                </tr>
                <tr>
                    <td>Sync Contacts</td>
                    <td><button id="syncContacts">Sync</button> <span id="syncContactsStatus"></span></td>
                </tr>
                <tr>
                    <td>Update Vendors</td>
                    <td><button id="manageVendors">Manage</button></td>
                </tr>
            </table>

            <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
            <script>
            $(document).ready(function () {
                $("#importProducts").click(function () {
                    $("#syncStatus").text("Importing...");
                    $.post("Functions/Product_Functions.php", { sync_products: true }, function (response) {
                        $("#syncStatus").text(response);
                    }).fail(function () {
                        $("#syncStatus").text("Error importing products.");
                    });
                });

                $("#syncContacts").click(function () {
                    $("#syncContactsStatus").text("Syncing contacts...");
                    $.post("Functions/Syncro_Contact_Sync.php", { sync_contacts: true }, function (response) {
                        $("#syncContactsStatus").text(response);
                    }).fail(function () {
                        $("#syncContactsStatus").text(" Error syncing contacts.");
                    });
                });

                $("#manageVendors").click(function () {
                    window.open("Vendors/Manage_Vendors.php", "ManageVendors", "width=600,height=400");
                });
            });
            </script>';
            break;
case 'edit_quote':
    $quoteId = $_GET['id'] ?? null;

    // 👇 Handle delete quote item
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_item_id'])) {
        $itemIdToDelete = $_POST['delete_item_id'];
        $deleteStmt = $pdo->prepare("DELETE FROM QuoteItems WHERE quote_item_id = ?");
        $deleteStmt->execute([$itemIdToDelete]);
    }

    if ($quoteId) {
        renderEditQuoteForm($pdo, $quoteId);
    } else {
        echo "<p> Quote ID is missing.</p>";
    }
    break;


        default:
            echo "<h2>Quotes Dashboard</h2><p>Welcome to the Quotes Dashboard. Choose an option from the left menu.</p>";
            break;
    }
} else {
    echo "<h2>Quotes Dashboard</h2><p>Welcome to the Quotes Dashboard. Choose an option from the left menu.</p>";
}

echo "</div>"; // End right-content
echo "</div>"; // End main-container
?>

 

Further to this I added the console.log the quoteItemId value inside the openEditQuantityPopup() and got this result. inspect shows correct value however popup is defiantly wrong item. image.thumb.png.355173edaf6f0cbeae0523f53544215d.png

i haven't looked that the code yet, but in Quotes/Edit_Quote_Quantity.php, log the $_GET variables so that you can see how many requests are made to it and what the inputs are -

file_put_contents('log.txt',print_r($_GET,true),FILE_APPEND);

 

so, i found the problem, with the help of php's error reporting, though the problem is in javascript.

you are echoing blocks of static html/javescript using php's heredoc syntax. when I made the test page i used, the javascript was simply in-line.

you are using template literals with embedded expressions in the javascript, e.g. ${some_var}. however, in php's heredoc syntax, this is the syntax for a php variable. so, php is putting the last value for any of its variables with the some_var name into the echoed javascript. how i found this is that the embedded expressions in the openUpdateTotalsPopup() javascrpt, for ${width}, ... produced undefined php variable errors.

the simplest fix would be to use php's nowdoc syntax. the correct solution would be to NOT echo blocks of static html/javascript, which I see i wrote  about in one of your previous threads.

@mac_gyver champion this fixed it

 


JS;
echo <<<'JS'
<script>
function openEditQuantityPopup(quoteItemId, quoteId) {
    const width = 400;
    const height = 200;

    console.log("Opening popup for quoteItemId:", quoteItemId, "quoteId:", quoteId);

    const left = (window.innerWidth - width) / 2;
    const top = (window.innerHeight - height) / 2;

    window.open(
        `Quotes/Edit_Quote_Quantity.php?quote_item_id=${quoteItemId}&quote_id=${quoteId}`,
        "EditQuoteQuantity",
        `width=${width},height=${height},top=${top},left=${left},resizable=no,scrollbars=no`
    );
}
</script>
JS;

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.