Skip to content
214 changes: 181 additions & 33 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,49 @@ h1 {
.query-section textarea {
margin-bottom: 1.5rem;
margin-top: -1.5rem;
border: 1px solid #00411a;
border-radius: 8px;
font-size: 1.15rem;
padding: 1.1rem;
background: #f7f7f7;
color: #067800;
transition: border 0.2s;
height: 160px;
min-height: 160px;
max-height: 160px;
resize: none;
max-height: 350px;
resize: vertical;
overflow-y: auto;
border: 1.5px solid #bdbdbd;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
overflow-x: hidden;
white-space: pre-wrap;
}

/* --- Unified custom scrollbar styles for textarea and JSON preview --- */
.query-section textarea,
.json-preview {
scrollbar-width: thin;
/* Firefox */
scrollbar-color: #009624 #e0e0e0;
/* Firefox */
overflow-x: hidden;
white-space: pre-wrap;
}

.query-section textarea:focus {
border: 1.5px solid var(--primary-green);
.query-section textarea::-webkit-scrollbar,
.json-preview::-webkit-scrollbar {
width: 10px;
background: #e0e0e0;
border-radius: 6px;
}

.query-section textarea::-webkit-scrollbar-thumb,
.json-preview::-webkit-scrollbar-thumb {
background: #009624;
border-radius: 6px;
}

.query-section textarea:focus,
.json-preview:focus {
border-color: #009624;
outline: none;
}

Expand Down Expand Up @@ -288,13 +316,18 @@ tr:nth-child(even) td {
}

.json-preview {
background: #f5f5f5;
padding: 1rem;
border-radius: 6px;
overflow-x: auto;
font-family: "Fira Mono", monospace;
font-size: 0.9rem;
margin: 1rem 0;
max-height: 350px;
padding: 1.1rem;
background: #f7f7f7;
color: #067800;
border: 1.5px solid #bdbdbd;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
overflow-x: hidden;
white-space: pre-wrap;
}

.preview-note {
Expand Down Expand Up @@ -383,28 +416,11 @@ p {
outline: none;
}

.preview-section {
margin-top: 1.5rem;
background: var(--card-bg);
border-radius: 8px;
padding: 1.5rem;
color: #222;
}

.json-preview {
background: #f5f5f5;
padding: 1rem;
border-radius: 6px;
overflow-x: auto;
font-family: "Fira Mono", monospace;
font-size: 0.9rem;
margin: 1rem 0;
}

.preview-note {
color: #666;
font-size: 0.9rem;
margin: 0;
/* Ensure Preview title is green */
.preview-section h2 {
color: #067800;
margin-bottom: 1rem;
margin-top: -2px;
}

.table-container {
Expand All @@ -427,4 +443,136 @@ h3 {
p {
margin: 0.5rem 0;
color: var(--text-light);
}

.sample-suggestions {
margin: 1.2rem 0 2rem 0;
display: flex;
align-items: center;
gap: 0.7rem;
flex-wrap: wrap;
padding: 1rem 1.5rem;
background: rgba(0, 150, 36, 0.07);
border: 1.5px solid #b9f6ca;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 200, 83, 0.06);
justify-content: flex-start;
}

.sample-suggestions span {
font-weight: 600;
font-size: 1.08rem;
margin-right: 0.5rem;
}

.sample-suggestions button {
background: #e0e0e0;
color: #067800;
border: 2px solid #009624;
border-radius: 20px;
padding: 0.5rem 1.4rem;
font-size: 1.08rem;
font-weight: 700;
cursor: pointer;
transition: background 0.2s, box-shadow 0.2s, border-color 0.2s;
box-shadow: 0 1px 4px rgba(0, 200, 83, 0.09);
outline: none;
}

.sample-suggestions button:hover {
background: #b9f6ca;
border-color: #00c853;
box-shadow: 0 2px 8px rgba(0, 200, 83, 0.18);
}

.json-input-section .sample-suggestions span {
color: #fff;
}

.sample-suggestions span {
color: #222;
}

.raw-json-section h2 {
margin-top: -2px;
color: #067800;
}

.app-summary-card {
background: #f7f7f7;
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
padding: 1.2rem 2rem 1.2rem 2rem;
margin-bottom: 2.2rem;
border: 1.5px solid #b9f6ca;
width: 100%;
box-sizing: border-box;
}

.app-summary {
color: #067800;
font-size: 1.13rem;
margin-bottom: 0.7rem;
text-align: center;
}

.app-guide {
color: #222;
font-size: 1.05rem;
margin: 0;
padding-left: 1.2rem;
text-align: left;
}

.app-guide li {
margin-bottom: 0.3rem;
}

@media (max-width: 600px) {
.container {
padding: 0.7rem;
}

.app-summary-card {
padding: 0.7rem 0.7rem 0.7rem 0.7rem;
font-size: 0.98rem;
}

.app-summary {
font-size: 1rem;
}

.app-guide {
font-size: 0.97rem;
padding-left: 0.7rem;
}

.sample-suggestions {
padding: 0.7rem;
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
}

.sample-suggestions button {
width: 100%;
min-width: 0;
text-align: left;
font-size: 1rem;
padding: 0.5rem 0.7rem;
}

.query-actions {
flex-direction: column;
align-items: stretch;
gap: 0.7rem;
}

.query-actions button,
.query-actions .clear-btn {
width: 100%;
min-width: 0;
box-sizing: border-box;
margin: 0;
}
}
87 changes: 82 additions & 5 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,35 @@
let previewData: string = "";
let inputMode: "file" | "raw" = "file";

// Sample data for suggestions
const sampleJsons = [
{
label: "US States Population",
value: `[
{ "state": "California", "region": "West", "pop": 39538223, "pop_male": 19453769, "pop_female": 20084454 },
{ "state": "Texas", "region": "South", "pop": 29145505, "pop_male": 14358470, "pop_female": 14787035 },
{ "state": "Florida", "region": "South", "pop": 21538187, "pop_male": 10470577, "pop_female": 11067610 }
]`,
},
// Add more samples if you want
];

const sampleSqls = [
{
label: "All States",
value: "SELECT * FROM table;",
},
{
label: "States with pop > 20M",
value: "SELECT state, pop FROM table WHERE pop > 20000000;",
},
{
label: "States in the South",
value: "SELECT state FROM table WHERE region = 'South';",
},
// Add more samples if you want
];

function saveHistory() {
sessionStorage.setItem("queryHistory", JSON.stringify(history));
sessionStorage.setItem("queryHistoryNextId", String(nextId));
Expand All @@ -34,7 +63,7 @@
try {
data = JSON.parse(input);
jsonError = null;
previewData = JSON.stringify(data.slice(0, 3), null, 2);
previewData = JSON.stringify(data, null, 2);
} catch (err) {
jsonError = "Invalid JSON input.";
data = [];
Expand Down Expand Up @@ -129,6 +158,27 @@

<main class="container">
<h1>SQL Query Parser</h1>
<div class="app-summary-card">
<p class="app-summary">
<strong>Welcome!</strong> This tool lets you quickly explore and analyze
your own JSON data using familiar SQL queries right in your browser,
with no setup or database required.
</p>
<ol class="app-guide">
<li>
<strong>Paste</strong> or <strong>upload</strong> your JSON data
below.
</li>
<li><strong>Preview</strong> your data instantly.</li>
<li>
<strong>Write</strong> an SQL query and click
<em>Execute Query</em>.
</li>
<li>
See results, errors, and your query history—all in one place!
</li>
</ol>
</div>

<div class="json-input-section">
<div class="input-mode-toggle">
Expand All @@ -148,6 +198,22 @@
</button>
</div>

<!-- Sample JSON suggestions -->
<div class="sample-suggestions">
<span>Try sample JSON:</span>
{#each sampleJsons as sample}
<button
type="button"
on:click={() => {
jsonInput = sample.value;
processJsonInput(sample.value);
}}
>
{sample.label}
</button>
{/each}
</div>

{#if inputMode === "file"}
<div
class="upload-zone"
Expand Down Expand Up @@ -183,6 +249,7 @@
</div>
{:else}
<div class="raw-json-section">
<h2>JSON Input</h2>
<textarea
bind:value={jsonInput}
placeholder="Paste your JSON data here..."
Expand All @@ -198,16 +265,27 @@

{#if previewData}
<div class="preview-section">
<h3>Data Preview</h3>
<h2>Preview</h2>
<pre class="json-preview">{previewData}</pre>
<p class="preview-note">
Showing first 3 records of {data.length} total records
Showing {data.length} total record{data.length === 1
? ""
: "s"}
</p>
</div>
{/if}
</div>

<div class="query-section">
<!-- Sample SQL suggestions -->
<div class="sample-suggestions">
<span>Try sample SQL:</span>
{#each sampleSqls as sample}
<button type="button" on:click={() => (query = sample.value)}>
{sample.label}
</button>
{/each}
</div>
<h2>SQL Query</h2>
<textarea
bind:value={query}
Expand Down Expand Up @@ -281,7 +359,7 @@

{#if history.length > 0}
<div class="history-section">
<h2>Query History</h2>
<h2>Query History ({history.length})</h2>
{#each history as item}
<div class="history-item">
<div class="query">{item.query}</div>
Expand All @@ -300,4 +378,3 @@
</div>
{/if}
</main>