<?php
error_reporting(E_ALL);
ini_set('display_errors', 0);
header('Content-Type: application/json');
$mysqli = new mysqli("localhost", "xxx", "xxx", "xxxx");
if ($mysqli->connect_error) {
echo json_encode(["error" => "DB connection failed: " . $mysqli->connect_error]);
exit;
}
$type = $_GET['type'] ?? '';
$value = $_GET['value'] ?? ''; // month or other
$symbol = $_GET['symbol'] ?? '';
$symbolsParam = $_GET['symbols'] ?? '';
$result = [];
if ($type === "symbols") {
$symbolsParam = $_GET['symbols'] ?? '';
$sql = "SELECT DISTINCT symbol, concat(symbol,' | ','Shares') company_name, 'TECH' sector
FROM stock
WHERE symbol IN ($symbolsParam)
ORDER BY symbol";
$res = $mysqli->query($sql);
while ($row = $res->fetch_assoc()) {
$result[] = [
"label" => $row['symbol'] . " (" . $row['company_name'] . ", " . $row['sector'] . ")",
"value" => $row['symbol'],
"nextType" => "symbol"
];
}
}
/*
elseif ($type === "symbol") {
// Under each symbol, show 3 fixed nodes
$result = [
["label" => "Database", "value" => $symbol, "nextType" => "database", "symbol" => $symbol],
["label" => "Allapps", "value" => $symbol, "nextType" => "allapps", "symbol" => $symbol],
["label" => "Microservices", "value" => $symbol, "nextType" => "microservices", "symbol" => $symbol]
];
}
*/
elseif ($type === "symbol") {
$result = [
["label" => "Database", "value" => $symbol, "nextType" => "database", "symbol" => $symbol, "cssClass" => "database-label"],
["label" => "Allapps", "value" => $symbol, "nextType" => "allapps", "symbol" => $symbol, "cssClass" => "allapps-label"],
["label" => "Microservices", "value" => $symbol, "nextType" => "microservices", "symbol" => $symbol, "cssClass" => "microservices-label"]
];
}
elseif ($type === "database") {
$stmt = $mysqli->prepare("SELECT * FROM myinv WHERE sym=?");
$stmt->bind_param("s", $symbol);
$stmt->execute();
$res = $stmt->get_result();
while ($row = $res->fetch_assoc()) {
$result[] = $row;
}
$stmt->close();
}
elseif ($type === "allapps") {
$stmt = $mysqli->prepare("SELECT * FROM corona WHERE symbol=?");
$stmt->bind_param("s", $symbol);
$stmt->execute();
$res = $stmt->get_result();
while ($row = $res->fetch_assoc()) {
$result[] = $row;
}
$stmt->close();
}
elseif ($type === "microservices") {
$stmt = $mysqli->prepare("SELECT * FROM stock WHERE symbol=?");
$stmt->bind_param("s", $symbol);
$stmt->execute();
$res = $stmt->get_result();
while ($row = $res->fetch_assoc()) {
$result[] = $row;
}
$stmt->close();
}
echo json_encode($result ?? []);
#################JS ###########################
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Stock TreeView</title>
<style>
body { font-family: Arial, sans-serif; background: #f9f9f9; padding: 20px; }
h2 { text-align: center; }
#inputArea { text-align: center; margin-bottom: 20px; }
textarea { width: 400px; padding: 8px; }
button { padding: 8px 12px; margin-left: 10px; cursor: pointer; }
ul.tree, ul.tree ul { list-style-type: none; margin: 0; padding: 0; }
ul.tree li { margin: 4px 0; cursor: pointer; }
.caret::before { content: "+ "; color: #007BFF; font-weight: bold; margin-right: 4px; }
.caret-down::before { content: "- "; }
.nested { display: none; margin-left: 20px; }
.active { display: block; }
.node-label { padding: 4px 8px; border-radius: 4px; }
.node-label:hover { background: #e6f0ff; }
table { border-collapse: collapse; width: 100%; margin-top: 10px; }
th, td { border: 1px solid #ccc; padding: 6px; text-align: left; }
th { background: #f4f4f4; }
input.search-box { margin-bottom: 8px; padding: 6px; width: 10%; }
</style>
</head>
<body>
<h2>Stock TreeView</h2>
<!-- Separate container for symbol input -->
<div id="symbolInputContainer">
<h3>Enter Symbols</h3>
<textarea id="symbolsInput" rows="3" placeholder="Enter symbols (space or line separated)"></textarea><br>
<button onclick="buildTree()">Build Tree</button>
</div>
<!-- Separate container for tree results -->
<div id="treeContainer"></div>
<script>
function buildTree() {
const input = document.getElementById("symbolsInput").value;
const symbols = input.split(/\s+/).filter(s => s.trim() !== "");
const formatted = symbols.map(s => `'${s.toUpperCase()}'`).join(",");
const container = document.getElementById("treeContainer");
container.innerHTML = "";
fetch(`backend.php?type=symbols&symbols=${encodeURIComponent(formatted)}`)
.then(res => res.json())
.then(data => {
if (!Array.isArray(data)) {
container.innerHTML = `<p style="color:red;">Error: ${data.error || "Invalid response"}</p>`;
return;
}
const ul = document.createElement("ul");
ul.className = "tree";
data.forEach(item => {
const li = document.createElement("li");
const span = document.createElement("span");
span.className = "caret node-label";
span.textContent = item.label;
span.onclick = () => toggleNode(span, item.nextType, item.value);
li.appendChild(span);
const nested = document.createElement("ul");
nested.className = "nested";
li.appendChild(nested);
ul.appendChild(li);
});
container.appendChild(ul);
})
.catch(err => {
container.innerHTML = `<p style="color:red;">Fetch error: ${err}</p>`;
});
}
function toggleNode(element, type, value, symbol="") {
element.classList.toggle("caret-down");
const nested = element.nextElementSibling;
if (!nested.classList.contains("active")) {
const url = `backend.php?type=${type}&value=${value}&symbol=${symbol || value}`;
fetch(url)
.then(res => res.json())
.then(data => {
nested.innerHTML = "";
if (!Array.isArray(data)) {
nested.innerHTML = `<li style="color:red;">Error: ${data.error || "Invalid response"}</li>`;
nested.classList.add("active");
return;
}
if (type === "database" || type === "allapps" || type === "microservices") {
const li = document.createElement("li");
const wrapper = document.createElement("div");
// Search box + table creation (same as before)
// ...
li.appendChild(wrapper);
// Append inside the child UL of Database/Allapps/Microservices
nested.appendChild(li);
if (data.length > 0) {
const wrapper = document.createElement("div");
// Search box
const searchBox = document.createElement("input");
searchBox.type = "text";
searchBox.placeholder = "Search...";
searchBox.className = "search-box";
// Table
const table = document.createElement("table");
if (type === "database") {
table.classList.add("database-table");
}
if (type === "allapps") {
table.classList.add("allapps-table");
}
if (type === "microservices") {
table.classList.add("microservices-table");
}
const headerRow = document.createElement("tr");
Object.keys(data[0]).forEach(key => {
const th = document.createElement("th");
th.textContent = key;
headerRow.appendChild(th);
});
table.appendChild(headerRow);
data.forEach(row => {
const tr = document.createElement("tr");
Object.values(row).forEach(val => {
const td = document.createElement("td");
td.textContent = val;
tr.appendChild(td);
});
table.appendChild(tr);
});
// Filter logic
searchBox.addEventListener("keyup", function() {
const filter = this.value.toLowerCase();
const rows = table.getElementsByTagName("tr");
for (let i = 1; i < rows.length; i++) { // skip header
let rowText = rows[i].textContent.toLowerCase();
rows[i].style.display = rowText.includes(filter) ? "" : "none";
}
});
wrapper.appendChild(searchBox);
wrapper.appendChild(table);
const li = document.createElement("li");
li.appendChild(wrapper);
nested.appendChild(li);
} else {
nested.innerHTML = "<li>No records found</li>";
}
} else {
data.forEach(item => {
const li = document.createElement("li");
const span = document.createElement("span");
span.className = "caret node-label " + (item.cssClass || "");
span.textContent = item.label;
span.onclick = () => toggleNode(span, item.nextType, item.value, item.symbol || symbol);
li.appendChild(span);
// Each child node gets its own nested UL
const childUl = document.createElement("ul");
childUl.className = "nested";
li.appendChild(childUl);
nested.appendChild(li);
});
}
nested.classList.add("active");
})
.catch(err => {
nested.innerHTML = `<li style="color:red;">Fetch error: ${err}</li>`;
nested.classList.add("active");
});
} else {
nested.classList.toggle("active");
}
}
</script>
<style>
/* General page styling */
body {
font-family: "Segoe UI", Roboto, Arial, sans-serif;
background: linear-gradient(135deg, #f0f4f8, #d9e2ec);
margin: 0;
padding: 20px;
color: #333;
}
h2 {
text-align: center;
font-size: 28px;
color: #2a4365;
margin-bottom: 20px;
}
/* Input area */
#inputArea {
text-align: center;
margin-bottom: 30px;
}
textarea {
width: 400px;
padding: 10px;
border: 2px solid #cbd5e0;
border-radius: 6px;
font-size: 14px;
resize: none;
transition: border-color 0.3s;
}
textarea:focus {
border-color: #3182ce;
outline: none;
}
button {
padding: 10px 18px;
margin-left: 10px;
cursor: pointer;
background: #3182ce;
color: #fff;
border: none;
border-radius: 6px;
font-size: 14px;
transition: background 0.3s;
}
button:hover {
background: #2b6cb0;
}
/* Tree styling */
ul.tree, ul.tree ul {
list-style-type: none;
margin: 0;
padding: 0;
}
ul.tree li {
margin: 6px 0;
cursor: pointer;
position: relative;
}
.caret::before {
font-family: "Font Awesome 5 Free";
content: "\f0da"; /* fa-caret-right */
font-weight: 900;
margin-right: 6px;
}
.caret::before {
content: "\25B6"; /* ? right-pointing triangle */
color: #3182ce;
font-weight: bold;
margin-right: 6px;
transition: transform 0.3s;
}
.caret-down::before {
content: "\25BC"; /* ? down-pointing triangle */
}
.node-label:hover {
background: #e2e8f0;
transform: translateX(3px);
}
.nested {
display: none;
margin-left: 20px;
}
.active {
display: block;
}
/* Shared table styling */
table {
border-collapse: collapse;
width: 95%;
margin: 15px auto;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
border-radius: 6px;
overflow: hidden;
}
th, td {
border: 1px solid #e2e8f0;
padding: 10px;
text-align: left;
font-size: 14px;
}
tr:nth-child(even) {
background: #f7fafc;
}
tr:hover {
background: #ebf8ff;
}
/* Search box styling */
input.search-box {
margin: 10px auto;
display: block;
padding: 8px 12px;
width: 50%;
border: 2px solid #cbd5e0;
border-radius: 6px;
font-size: 14px;
transition: border-color 0.3s;
}
input.search-box:focus {
border-color: #3182ce;
outline: none;
}
/* Section-specific themes */
.database-table th {
background: #2b6cb0; /* Deep blue */
color: #fff;
}
.allapps-table th {
background: #38a169; /* Green */
color: #fff;
}
.microservices-table th {
background: #d69e2e; /* Amber/Orange */
color: #fff;
}
/* Section-specific label icons */
.database-label::before {
content: "??? "; /* database cylinder/file cabinet */
}
.allapps-label::before {
content: "?? "; /* app icon (mobile) */
}
.microservices-label::before {
content: "?? "; /* gear for microservices */
}
.database-label::before {
content: "\25A3 "; /* ? square with fill */
color: #2b6cb0;
}
.allapps-label::before {
content: "\25A0 "; /* ¦ solid square */
color: #38a169;
}
.microservices-label::before {
content: "\25CF "; /* ? solid circle */
color: #d69e2e;
}
/* Extra indentation for tables under child nodes */
.nested li div {
margin-left: 30px; /* pushes the wrapper (search + table) to the right */
}
.database-table {
margin-left: 30px;
}
.allapps-table {
margin-left: 30px;
}
.microservices-table {
margin-left: 30px;
}
/* Indent the child headings under each symbol */
.database-label,
.allapps-label,
.microservices-label {
margin-left: 25px; /* push the caret + label right */
display: inline-block;
}
ul.tree ul li .node-label {
margin-left: 25px;
}
#symbolInputContainer {
max-width: 500px;
margin: 0 auto 30px auto;
padding: 20px;
background: #ffffff;
border: 2px solid #cbd5e0;
border-radius: 8px;
box-shadow: 0 4px 10px rgba(0,0,0,0.05);
text-align: center;
}
#symbolInputContainer h3 {
margin-bottom: 15px;
color: #2a4365;
font-size: 20px;
}
/* Smaller search box */
input.search-box {
margin: 8px auto;
display: block;
padding: 5px 8px; /* reduced padding */
width: 35%; /* narrower width */
border: 2px solid #cbd5e0;
border-radius: 6px;
font-size: 13px; /* slightly smaller font */
transition: border-color 0.3s;
}
input.search-box:focus {
border-color: #3182ce;
outline: none;
}
/* Larger font for symbols */
ul.tree > li > .node-label {
font-size: 18px; /* bigger font for main symbols */
font-weight: 600;
color: #2a4365;
}
/* Larger font for Database / Allapps / Microservices headings */
.database-label,
.allapps-label,
.microservices-label {
font-size: 16px; /* bigger font for child headings */
font-weight: 500;
color: #1a202c;
margin-left: 25px; /* indentation to push them right */
display: inline-block;
}
#pageFooter {
text-align: center;
margin-top: 40px;
padding: 15px;
font-size: 14px;
font-weight: 500;
color: #2a4365;
background: #edf2f7;
border-top: 2px solid #cbd5e0;
border-radius: 0 0 8px 8px;
}
</style>
<!-- Footer -->
<footer id="pageFooter">
Developed by Dilip
</footer>
</body>
</body>
</html>
No comments:
Post a Comment