From 434a8b6c6d1a8df0a1eaf42d216eab0ef662adef Mon Sep 17 00:00:00 2001 From: Suriya Date: Wed, 20 May 2026 16:11:13 +0530 Subject: [PATCH] rest endpoints --- Nearle_Full_API_Documentation.docx | Bin 0 -> 37880 bytes scratch/docx_content.txt | Bin 0 -> 11402 bytes scratch/docx_content_utf8.txt | 233 +++++++++++++++++++++++ scratch/extract_docx.py | 15 ++ src/App.jsx | 122 ++++-------- src/components/EndpointViewer.jsx | 294 +++++++++++++++++++---------- src/components/Introduction.jsx | 103 ++++++++++ src/components/Sidebar.jsx | 111 ++++++----- src/data/apiData.js | 4 +- src/data/restTopics.js | 177 +++++++++++++++++ src/lib/highlight.js | 26 +++ test_portal.py | 39 ++++ 12 files changed, 886 insertions(+), 238 deletions(-) create mode 100644 Nearle_Full_API_Documentation.docx create mode 100644 scratch/docx_content.txt create mode 100644 scratch/docx_content_utf8.txt create mode 100644 scratch/extract_docx.py create mode 100644 src/components/Introduction.jsx create mode 100644 src/data/restTopics.js create mode 100644 src/lib/highlight.js create mode 100644 test_portal.py diff --git a/Nearle_Full_API_Documentation.docx b/Nearle_Full_API_Documentation.docx new file mode 100644 index 0000000000000000000000000000000000000000..b1feea836bbdf000485b48c7d894911d4627c5a9 GIT binary patch literal 37880 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 literal 0 HcmV?d00001 diff --git a/scratch/docx_content.txt b/scratch/docx_content.txt new file mode 100644 index 0000000000000000000000000000000000000000..b6093c414a4e1642ef3ba48a828b34c5d9d0d85a GIT binary patch literal 11402 zcmeHNTWecK5Z>oP|AT8BNFf31F7++AZ3v{z#UU@H7{|A`^(~g#;u!z(LfiRvb~Lkd z_8hH>-KQdCX?13I=km>EXZ`nI+u@tA5q=CuVLx1lGy2>JKZMKhA)Kbsv+z2+pkM!_ z_xIs9`t^*yJtyk@a1}m=H{m6Xzoj_`^z@uoxCje+wxAU*>HC-Ai_nX^Jf~-iutQXH z`n-&^*EAb5m3|&)^y7@T;k&RK-qHH6BY*oeXHHMB<{(nshRwLIUGX#=(yx$f9Jb^8 zF3uRn-#q7Uh@T^p<|eH>id3JLze3hJz8{CJA}``*rN19Y zhNC5BdVw*p4r+RV5m83LE8-V2U(+7%36sn7H;AMB@`BeBKDP55b_Ub2GF`6#?@H05kNq^y6#ET48~jJvw5Tf zN{|Ji7pAb0NO#P07Ixi>h`^kmqL!6|+@7d$PGhv;^>fr>2fTkyh|04bXP|x~(@8|) z6&2$^#=u|}e0r2`WxwzY&47yifkSRCAJ5A%s1zIvkcTF43$tLtH^B_%R?9uS?_26+@koq#;f&+>S8Kt9SR zt^@MZ3mP$%Mk}!Z*W^4JB`bS-wE602ZHteV7B8Ki-jXzIW5gqlM5AQ;F651p1#6Ip zT2SLJs>oFp;%Hgx=cikb(ou?gt5NFZtVivA)JUUr$^hOx*7jn>ZEf&S_=hBF2cH-5 zv^x)~|Bl?r6K4jMK)i=fAmU>isruE7hjSIUz>B?MoX{;Jt_y2@W1MjNFqj-C#B;=c z9cv_<^x*Bg^!b6l@yYIl^oTkf^*&<2IH9@ApT-Hv%)4FZhF0P}3cLoVMA1$;%X=Rg zCtEdrq*ey@l_pQHU3))8I}hkjT~RGKFKFqeCEAyF^Obe3an_Vni;C8X!5Oet=0i|B zNf;E|mZ@zfn3yV%Z8J$olu^0k)fVF?2`}|nm?ZQtHlIa(@3f$Cl44O88Yjz&P$Xb$ zdQbFNn1{nr zsBhXjk1Jj_L=(?zGm>!DZRfc;L;ZbbtbUcn={>6M(O*YLk~Lk*wI%L+>}>O1gDCtHg1aPk}Ez3o)v4-QKq+wQ=Zus6^NF9`LV-2IiYGh!25QPi>$Df)-Re zvv1(JRySf{{0a@~Sdf{YVcI=J?o?_#q$G8YxL(3S9?%`A zKg~*v#hn)H(~YbCvPN2+6Y`!gu)az6Prp!n|45j|O_XY(_I^pa#ukCQM!Fr+Kl&na zM~>c9ef5%a3~l5$G+MF1R}~3OotCiba}w6~SoJi(DykHz19VPZ2R`Rm@yOWCb*0hN zcgbaU#`VBdYhpp^h3i=Eersc?bi`|7X>O-3WDOEtPY5Fmx@pyFL%a3j0n%0P_5kSv z%P9fzn31rm{stvmz@nF={XnsFwb)^2;){;KyL&aZseFMMlvHAiMM+eufo zX)Q#Bed6=DGP+nVls+u9uM*#9yg|#$7nZCw zrQg@g3%*X5>@cAS2;Fr@BijkI8iMBYYF|5mtKyLK|GM$?lJL*nGXC$u+RDcwOS*_2 zS+)OB=OzBPSc9c7S6<#G8n>i>*+!Wo({?NcYts}hbi8gwE`7*$?CIJZi5Yc##__TV z-lkRcxbIow3{_i8OTV&-D?ZIN5v8?;^f94#Ijea|EOlOamL*rKN~f~Us}$}FoT%bh^ZK+<{Zjuo?na^S}Q#}Q)1IQ~zb?|}PA@(+Z0tw#U= literal 0 HcmV?d00001 diff --git a/scratch/docx_content_utf8.txt b/scratch/docx_content_utf8.txt new file mode 100644 index 0000000..a543282 --- /dev/null +++ b/scratch/docx_content_utf8.txt @@ -0,0 +1,233 @@ +0: Nearle Mobile API – Full GraphQL Documentation +1: GetCustomerLocations +2: REST Params: +3: {"customerid": 6060} +4: GraphQL Query: +5: query GetCustomerLocations($customerid: bigint!) { +6: customer_locations(where: { customerid: { _eq: $customerid } }) { +7: locationid +8: latitude +9: longitude +10: address +11: } +12: } +13: GraphQL Variables: +14: {"customerid": 6060} +15: GetCustomerOrdersV3 +16: REST Params: +17: {"customerid":6060,"tenantid":1087,"moduleid":2,"fromdate":"2026-01-01T00:00:00","todate":"2026-12-31T23:59:59","orderstatus":"delivered","keyword":"%pizza%","limit":10,"offset":0} +18: GraphQL Query: +19: query GetCustomerOrders($customerid: bigint!, $tenantid: bigint!, $moduleid: bigint!, $fromdate: timestamptz!, $todate: timestamptz!, $orderstatus: String!, $keyword: String, $limit: Int!, $offset: Int!) { +20: orders( +21: where: { +22: customerid: { _eq: $customerid } +23: tenantid: { _eq: $tenantid } +24: moduleid: { _eq: $moduleid } +25: orderstatus: { _eq: $orderstatus } +26: orderdate: { _gte: $fromdate, _lte: $todate } +27: _or: [{ orderid: { _ilike: $keyword } }] +28: } +29: limit: $limit +30: offset: $offset +31: ) { +32: orderid +33: orderstatus +34: orderamount +35: } +36: } +37: GraphQL Variables: +38: {"customerid":6060,"tenantid":1087,"moduleid":2,"fromdate":"2026-01-01T00:00:00","todate":"2026-12-31T23:59:59","orderstatus":"delivered","keyword":"%pizza%","limit":10,"offset":0} +39: GetCustomer +40: REST Params: +41: {"customerid":6060} +42: GraphQL Query: +43: query GetCustomer($customerid: bigint!) { +44: customers(where: { customerid: { _eq: $customerid } }) { +45: customerid +46: name +47: contactno +48: } +49: } +50: GraphQL Variables: +51: {"customerid":6060} +52: GetCustomerRequests +53: REST Params: +54: {"customerid":6060,"limit":10,"offset":0} +55: GraphQL Query: +56: query GetCustomerRequests($customerid: bigint!, $limit: Int!, $offset: Int!) { +57: customer_requests(where: { customerid: { _eq: $customerid } }, limit: $limit, offset: $offset) { +58: requestid +59: status +60: } +61: } +62: GraphQL Variables: +63: {"customerid":6060,"limit":10,"offset":0} +64: GetProductSubcategories +65: REST Params: +66: {"categoryid":1001} +67: GraphQL Query: +68: query GetProductSubcategories($categoryid: bigint!) { +69: app_subcategory(where: { categoryid: { _eq: $categoryid } }) { +70: subcategoryid +71: subcategoryname +72: } +73: } +74: GraphQL Variables: +75: {"categoryid":1001} +76: GetAppCategories +77: REST Params: +78: {} +79: GraphQL Query: +80: query GetAppCategories { +81: app_category { +82: categoryid +83: categoryname +84: } +85: } +86: GraphQL Variables: +87: {} +88: GetProductVariants +89: REST Params: +90: {"tenantid":1087,"subcategoryid":14} +91: GraphQL Query: +92: query GetProductVariants($tenantid: bigint!, $subcategoryid: bigint!) { +93: product_variants(where: { tenantid: { _eq: $tenantid }, subcategoryid: { _eq: $subcategoryid } }) { +94: variantid +95: productname +96: price +97: } +98: } +99: GraphQL Variables: +100: {"tenantid":1087,"subcategoryid":14} +101: GetTenantPromotions +102: REST Params: +103: {"tenantid":1087,"locationid":1} +104: GraphQL Query: +105: query GetTenantPromotions($tenantid: bigint!, $locationid: bigint!) { +106: promotions(where: { tenantid: { _eq: $tenantid }, locationid: { _eq: $locationid } }) { +107: promotionid +108: title +109: } +110: } +111: GraphQL Variables: +112: {"tenantid":1087,"locationid":1} +113: GetAppConfig +114: REST Params: +115: {"configid":15} +116: GraphQL Query: +117: query GetAppConfig($configid: bigint!) { +118: app_config(where: { configid: { _eq: $configid } }) { +119: configkey +120: configvalue +121: } +122: } +123: GraphQL Variables: +124: {"configid":15} +125: searchcustomers +126: REST Params: +127: {"tenantid":1087,"keyword":"%john%"} +128: GraphQL Query: +129: query SearchCustomers($tenantid: bigint!, $keyword: String!) { +130: customers(where: { tenantid: { _eq: $tenantid }, name: { _ilike: $keyword } }) { +131: customerid +132: name +133: } +134: } +135: GraphQL Variables: +136: {"tenantid":1087,"keyword":"%john%"} +137: getTenantorders +138: REST Params: +139: {} +140: GraphQL Query: +141: query GetTenantOrders { +142: orders { +143: orderid +144: tenantid +145: } +146: } +147: GraphQL Variables: +148: {} +149: getstaff +150: REST Params: +151: {"tenantid":1087} +152: GraphQL Query: +153: query GetStaff($tenantid: bigint!) { +154: staff(where: { tenantid: { _eq: $tenantid } }) { +155: staffid +156: name +157: } +158: } +159: GraphQL Variables: +160: {"tenantid":1087} +161: GetTenantInfo +162: REST Params: +163: {"tenantid":1079} +164: GraphQL Query: +165: query GetTenantInfo($tenantid: bigint!) { +166: tenants(where: { tenantid: { _eq: $tenantid } }) { +167: tenantname +168: city +169: } +170: } +171: GraphQL Variables: +172: {"tenantid":1079} +173: getTenantlocations +174: REST Params: +175: {"tenantid":1} +176: GraphQL Query: +177: query GetTenantLocations($tenantid: bigint!) { +178: tenant_locations(where: { tenantid: { _eq: $tenantid } }) { +179: locationid +180: locationname +181: } +182: } +183: GraphQL Variables: +184: {"tenantid":1} +185: getapplocations +186: REST Params: +187: {} +188: GraphQL Query: +189: query GetAppLocations { +190: app_location { +191: applocationid +192: locationname +193: } +194: } +195: GraphQL Variables: +196: {} +197: getsubcategory +198: REST Params: +199: {"moduleid":6,"categoryid":1} +200: GraphQL Query: +201: query GetSubCategory($moduleid: bigint!, $categoryid: bigint!) { +202: app_subcategory(where: { categoryid: { _eq: $categoryid }, category: { modules: { moduleid: { _eq: $moduleid } } } }) { +203: subcategoryid +204: subcategoryname +205: } +206: } +207: GraphQL Variables: +208: {"moduleid":6,"categoryid":1} +209: GetPartners +210: REST Params: +211: {"applocationid":1,"partnerid":44,"limit":10,"offset":0} +212: GraphQL Query: +213: query GetPartners($applocationid: bigint!, $partnerid: bigint, $limit: Int!, $offset: Int!) { +214: partners(where: { applocationid: { _eq: $applocationid }, partnerid: { _eq: $partnerid } }, limit: $limit, offset: $offset) { +215: partnerid +216: name +217: } +218: } +219: GraphQL Variables: +220: {"applocationid":1,"partnerid":44,"limit":10,"offset":0} +221: GetlocationsConfig +222: REST Params: +223: {} +224: GraphQL Query: +225: query GetLocationConfig { +226: app_locationconfigs { +227: applocationid +228: configkey +229: } +230: } +231: GraphQL Variables: +232: {} diff --git a/scratch/extract_docx.py b/scratch/extract_docx.py new file mode 100644 index 0000000..32a9efb --- /dev/null +++ b/scratch/extract_docx.py @@ -0,0 +1,15 @@ +import docx +import json + +def extract_docx_content(file_path): + doc = docx.Document(file_path) + full_text = [] + for para in doc.paragraphs: + full_text.append(para.text) + return "\n".join(full_text) + +content = extract_docx_content('Nearle_Full_API_Documentation.docx') +with open('scratch/docx_content_utf8.txt', 'w', encoding='utf-8') as f: + lines = content.split('\n') + for i, line in enumerate(lines): + f.write(f"{i}: {line}\n") diff --git a/src/App.jsx b/src/App.jsx index 2881c1b..b98bf6c 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,116 +1,66 @@ import React, { useState, useMemo } from 'react'; import Sidebar from './components/Sidebar'; import EndpointViewer from './components/EndpointViewer'; -import { topics } from './data/apiData'; -import { ArrowRight, Code2, Zap, Users, ShoppingCart, Home, Box, Link2 } from 'lucide-react'; +import Introduction from './components/Introduction'; +import { graphqlTopics, GRAPHQL_BASE_URL } from './data/apiData'; +import { restTopics, REST_BASE_URL } from './data/restTopics'; -const topicIcons = { - users: Users, - orders: ShoppingCart, - tenants: Home, - products: Box, - locations: Link2, - partners: Users, -}; +const processTopics = (topics, baseUrl, type) => + topics.map(t => ({ ...t, baseUrl, type, uniqueId: `${type}-${t.id}` })); + +const allGraphql = processTopics(graphqlTopics, GRAPHQL_BASE_URL, 'graphql'); +const allRest = processTopics(restTopics, REST_BASE_URL, 'rest'); + +function filterTopics(topics, q) { + if (!q) return topics; + return topics.filter(t => + t.name.toLowerCase().includes(q) || + (t.description || '').toLowerCase().includes(q) || + t.endpoints.some(e => + e.name.toLowerCase().includes(q) || + e.url.toLowerCase().includes(q) || + (e.description || '').toLowerCase().includes(q) + ) + ); +} function App() { const [activeTopic, setActiveTopic] = useState(null); const [searchQuery, setSearchQuery] = useState(''); - const filteredTopics = useMemo(() => { - if (!searchQuery.trim()) return topics; - - return topics.map(topic => { - const matchTopic = topic.name.toLowerCase().includes(searchQuery.toLowerCase()); - const filteredEndpoints = topic.endpoints.filter(ep => - ep.name.toLowerCase().includes(searchQuery.toLowerCase()) || - ep.description.toLowerCase().includes(searchQuery.toLowerCase()) - ); - - if (matchTopic || filteredEndpoints.length > 0) { - return { - ...topic, - endpoints: filteredEndpoints.length > 0 ? filteredEndpoints : topic.endpoints - }; - } - return null; - }).filter(Boolean); - }, [searchQuery]); + const q = searchQuery.trim().toLowerCase(); + const visibleGraphql = useMemo(() => filterTopics(allGraphql, q), [q]); + const visibleRest = useMemo(() => filterTopics(allRest, q), [q]); return (
- + {/* Ambient background glows */}
- {/* Sidebar */} - - {/* Main Content Area */}
{activeTopic ? (
) : ( -
- -
- - v2.0 Developer API -
- -

- NearleDaily API -

- -

- A comprehensive, lightning-fast platform designed for logistics, order management, and multi-tenant POS administration. -

- -
- {topics.map((topic, index) => { - const Icon = topicIcons[topic.id] || Zap; - return ( -
setActiveTopic(topic)} - className="group relative bg-white p-6 rounded-2xl border border-slate-200/60 shadow-sm hover:shadow-xl hover:shadow-brand-500/5 hover:border-brand-200 transition-all duration-300 cursor-pointer overflow-hidden" - style={{ animationDelay: `${index * 100}ms` }} - > -
- -
-

-
- -
- {topic.name} - -

-

- {topic.description} -

-
-
- )})} -
- -
- -

- Explore real-time interactive endpoints. All requests are authenticated with secure admin secrets internally for demonstration purposes. -

-
- +
+
)}
diff --git a/src/components/EndpointViewer.jsx b/src/components/EndpointViewer.jsx index de90107..b0b2706 100644 --- a/src/components/EndpointViewer.jsx +++ b/src/components/EndpointViewer.jsx @@ -1,86 +1,120 @@ import React, { useState, useEffect } from 'react'; -import { Play, FileJson, Server, CheckCircle2, AlertCircle } from 'lucide-react'; +import { Play, FileJson, Server, CheckCircle2, AlertCircle, Copy, Check, Loader2 } from 'lucide-react'; import { graphqlMeta } from '../data/apiData'; +import { highlightJSON } from '../lib/highlight'; + +function safeDecode(v) { + try { return decodeURIComponent(v); } catch { return v; } +} + +function parseUrlParams(url) { + const [, query = ''] = url.split('?'); + const params = {}; + if (query) { + for (const pair of query.split('&')) { + const [name, value = ''] = pair.split('='); + if (name) params[name] = safeDecode(value); + } + } + return params; +} + +function EndpointRow({ endpoint, topic }) { + const isRest = topic.type === 'rest'; + const meta = !isRest ? graphqlMeta[endpoint.name] : null; -function EndpointRow({ endpoint }) { - const meta = graphqlMeta[endpoint.name]; const [queryText, setQueryText] = useState(meta?.query || ''); const [variablesText, setVariablesText] = useState(meta?.variables || '{}'); - - const parseParams = (url) => { - const parts = url.split('?'); - if(parts.length < 2) return {}; - const sp = new URLSearchParams(parts[1]); - const obj = {}; - for(const [k, v] of sp.entries()) obj[k] = v; - return obj; - }; - - const [params, setParams] = useState(parseParams(endpoint.url)); + const [params, setParams] = useState(() => parseUrlParams(endpoint.url)); const [result, setResult] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); + const [copied, setCopied] = useState(false); useEffect(() => { setQueryText(meta?.query || ''); setVariablesText(meta?.variables || '{}'); - }, [meta?.query, meta?.variables]); - - useEffect(() => { - setParams(parseParams(endpoint.url)); - }, [endpoint.url]); - - useEffect(() => { - try { - const parsed = variablesText?.trim() ? JSON.parse(variablesText) : {}; - if(endpoint.method === 'GET') { - const next = {}; - Object.keys(params).forEach(k => { - next[k] = parsed[k] !== undefined ? String(parsed[k]) : params[k]; - }); - setParams(next); - } - } catch(e) {} + setParams(parseUrlParams(endpoint.url)); + setResult(null); + setError(null); }, [endpoint.name]); + const copyResponse = async () => { + if (!result) return; + try { + await navigator.clipboard.writeText(JSON.stringify(result.data, null, 2)); + setCopied(true); setTimeout(() => setCopied(false), 1500); + } catch {} + }; + const execute = async () => { setError(null); setIsLoading(true); setResult(null); try { - const base = 'https://api.workolik.com'; - let requestUrl = base + endpoint.url; - const options = { - method: endpoint.method, - headers: { - 'x-hasura-admin-secret': 'nearle-admin-secret', - 'Content-Type': 'application/json' - } - }; - - if (endpoint.method === 'GET' && !endpoint.useGraphql) { - const emptyKeys = Object.entries(params).filter(([k,v]) => String(v).trim() === '').map(([k])=>k); - if (emptyKeys.length) { - setError('Required parameter(s): ' + emptyKeys.join(', ')); - setIsLoading(false); - return; - } + if (isRest) { + // REST: fetch directly (fiesta.nearle.app supports CORS) const path = endpoint.url.split('?')[0]; - const qs = new URLSearchParams(params).toString(); - requestUrl = base + path + (qs ? '?' + qs : ''); - } else { - const parsedVariables = variablesText?.trim() ? JSON.parse(variablesText) : {}; - requestUrl = base + '/v1/graphql'; - options.method = 'POST'; - options.body = JSON.stringify({ query: queryText, variables: parsedVariables }); - } + const isGet = endpoint.method === 'GET'; + let url = topic.baseUrl + endpoint.url; - const res = await fetch(requestUrl, options); - const data = await res.json(); - - setResult({ status: res.status, ok: res.ok, data }); - } catch(err) { + if (isGet && Object.keys(params).length > 0) { + const qs = new URLSearchParams(params).toString(); + url = topic.baseUrl + path + (qs ? '?' + qs : ''); + } + + const options = { + method: endpoint.method, + headers: { 'Content-Type': 'application/json' }, + }; + + if (!isGet && endpoint.body) { + options.body = typeof endpoint.body === 'string' + ? endpoint.body + : JSON.stringify(endpoint.body); + } + + const res = await fetch(url, options); + const text = await res.text(); + let data; + try { data = JSON.parse(text); } catch { data = text; } + setResult({ status: res.status, ok: res.ok, data }); + + } else { + // GraphQL / Hasura + const base = topic.baseUrl; + let requestUrl = base + endpoint.url; + const options = { + method: endpoint.method, + headers: { + 'x-hasura-admin-secret': 'nearle-admin-secret', + 'Content-Type': 'application/json', + }, + }; + + if (endpoint.method === 'GET' && !endpoint.useGraphql) { + const emptyKeys = Object.entries(params).filter(([, v]) => String(v).trim() === '').map(([k]) => k); + if (emptyKeys.length) { + setError('Required parameter(s): ' + emptyKeys.join(', ')); + setIsLoading(false); + return; + } + const path = endpoint.url.split('?')[0]; + const qs = new URLSearchParams(params).toString(); + requestUrl = base + path + (qs ? '?' + qs : ''); + } else { + const parsedVars = variablesText?.trim() ? JSON.parse(variablesText) : {}; + requestUrl = base + '/v1/graphql'; + options.method = 'POST'; + options.body = JSON.stringify({ query: queryText, variables: parsedVars }); + } + + const res = await fetch(requestUrl, options); + const data = await res.json(); + setResult({ status: res.status, ok: res.ok, data }); + } + } catch (err) { setError(String(err)); } finally { setIsLoading(false); @@ -88,16 +122,19 @@ function EndpointRow({ endpoint }) { }; const methodColor = { - GET: 'bg-emerald-100/50 text-emerald-700 border-emerald-200', - POST: 'bg-blue-100/50 text-blue-700 border-blue-200', - PUT: 'bg-amber-100/50 text-amber-700 border-amber-200', - DELETE: 'bg-red-100/50 text-red-700 border-red-200' + GET: 'bg-emerald-100/50 text-emerald-700 border-emerald-200', + POST: 'bg-blue-100/50 text-blue-700 border-blue-200', + PUT: 'bg-amber-100/50 text-amber-700 border-amber-200', + DELETE: 'bg-red-100/50 text-red-700 border-red-200', + PATCH: 'bg-purple-100/50 text-purple-700 border-purple-200', }[endpoint.method] || 'bg-slate-100/50 text-slate-700 border-slate-200'; + const urlPath = endpoint.url.split('?')[0]; + return (
- + {/* Left Column: Description & Parameters */}
@@ -114,10 +151,11 @@ function EndpointRow({ endpoint }) {
- https://api.workolik.com - {endpoint.url.split('?')[0]} + {topic.baseUrl} + {urlPath}
+ {/* Query params (GET endpoints) */} {endpoint.method === 'GET' && Object.keys(params).length > 0 && (

@@ -130,22 +168,21 @@ function EndpointRow({ endpoint }) { {key} string - { const newVal = e.target.value; - setParams(p => { - const next = {...p, [key]: newVal}; + setParams(p => ({ ...p, [key]: newVal })); + if (!isRest) { try { setVariablesText(JSON.stringify({ ...JSON.parse(variablesText || '{}'), [key]: isNaN(newVal) || newVal === '' ? newVal : Number(newVal) }, null, 2)); - } catch(err) {} - return next; - }); + } catch {} + } }} />

@@ -155,10 +192,10 @@ function EndpointRow({ endpoint }) { )}
- {/* Right Column: Execution & Code */} + {/* Right Column: Code Panel */}
- + {/* macOS window dots */}
@@ -167,23 +204,24 @@ function EndpointRow({ endpoint }) {
Request Payload
+ {/* Pane content */} {meta ? ( + // GraphQL editor: query + variables
GraphQL Query
-