diff --git a/deno.json b/deno.json index 427b648..85db2d7 100644 --- a/deno.json +++ b/deno.json @@ -25,6 +25,7 @@ "autoprefixer": "npm:autoprefixer@^10.4.20", "bits-ui": "npm:bits-ui@^0.21.16", "clsx": "npm:clsx@^2.1.1", + "detect-url-change": "npm:detect-url-change@^1.0.2", "lucide-svelte": "npm:lucide-svelte@^0.462.0", "mode-watcher": "npm:mode-watcher@^0.5.0", "postcss": "npm:postcss@^8.4.49", diff --git a/deno.lock b/deno.lock index a94e8cf..31e12f4 100644 --- a/deno.lock +++ b/deno.lock @@ -23,6 +23,7 @@ "npm:autoprefixer@^10.4.20": "10.4.20_postcss@8.4.49", "npm:bits-ui@~0.21.16": "0.21.16_svelte@5.2.10__acorn@8.14.0", "npm:clsx@^2.1.1": "2.1.1", + "npm:detect-url-change@^1.0.2": "1.0.2", "npm:hono-rate-limiter@*": "0.2.3_hono@4.6.5", "npm:hono@*": "4.6.5", "npm:js-yaml@^4.0.9": "4.1.0", @@ -686,6 +687,12 @@ "dequal@2.0.3": { "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" }, + "detect-url-change@1.0.2": { + "integrity": "sha512-kw8H5SvDszrszffxBpfJ0zYQWbqNMxBuxUxz4tVwZVQMhhZmVShiXrPgEZx30H+J+iXQmmm1U39Ti2nUmIlG5g==", + "dependencies": [ + "events" + ] + }, "didyoumean@1.2.2": { "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" }, @@ -780,6 +787,9 @@ "@types/estree" ] }, + "events@3.3.0": { + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, "execa@7.2.0": { "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", "dependencies": [ @@ -1689,6 +1699,7 @@ "npm:autoprefixer@^10.4.20", "npm:bits-ui@~0.21.16", "npm:clsx@^2.1.1", + "npm:detect-url-change@^1.0.2", "npm:lucide-svelte@0.462", "npm:mode-watcher@0.5", "npm:postcss@^8.4.49", diff --git a/routes/repository.ts b/routes/repository.ts index 5ed91fb..8a30958 100644 --- a/routes/repository.ts +++ b/routes/repository.ts @@ -88,4 +88,49 @@ app.get('/repositories', async (c) => { } }); +app.get('/repositories/search', async (c) => { + console.log('Searching repositories'); + + try { + const text = c.req.query('text') || ''; + + if (!text) { + return c.json({ error: 'Search text is required' }, 400); + } + + console.log('Received query parameters:', { + text: c.req.query('text'), + page: c.req.query('page'), + limit: c.req.query('limit'), + }); + + const repositories = await sql` + SELECT * + FROM repository + WHERE name ILIKE '%' || ${text} || '%' + OR author ILIKE '%' || ${text} || '%' + LIMIT ${LIMIT_PER_PAGE}; + `; + + return c.json({ + data: repositories, + pagination: { + currentPage: 1, + totalPages: 1, + totalItems: repositories.length, + itemsPerPage: LIMIT_PER_PAGE, + hasNextPage: false, + hasPrevPage: false, + }, + sort: { + sortBy: 'stars', + order: 'desc', + }, + }); + } catch (error) { + console.error('Error searching Neon database:', error); + return c.json({ error: 'Failed to search repositories' }, 500); + } +}); + export default app; diff --git a/src/App.svelte b/src/App.svelte index ecb85ce..4a3c521 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -1,40 +1,15 @@ @@ -43,43 +18,14 @@
-
- - -
- - - - -
+
+ + + + + + +
diff --git a/src/lib/components/navigation/navigation.svelte b/src/lib/components/navigation/navigation.svelte index bac7c26..02facdf 100644 --- a/src/lib/components/navigation/navigation.svelte +++ b/src/lib/components/navigation/navigation.svelte @@ -1,4 +1,5 @@ -
+
; + export function debounce any>( func: T, wait: number ): (...args: Parameters) => void { - let timeoutId: ReturnType; - return (...args: Parameters) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => { diff --git a/src/lib/pages/docs/get.svelte b/src/lib/pages/docs/get.svelte new file mode 100644 index 0000000..3f04aa0 --- /dev/null +++ b/src/lib/pages/docs/get.svelte @@ -0,0 +1,122 @@ + + +
+
+

Get Repositories

+

Get Repositories from the database

+ +
+ + GET + + /v1/repositories +
+ +

Request

+

Query Parameters

+ + {#each parameters as param} +
+
+

{param.name}

+

+ {param.type} +

+
+ +

{param.description}

+
+ {/each} +
+ +
+
+

curl --request GET \

+

--url https://api.naijastars.dev/v1/repositories \

+
+ +
+
+        
+          {`{
+  "status": "success",
+  "data": [   [
+    {
+        "id": 34,
+        "name": "chakra-ui",
+        "link": "https://github.com/chakra-ui/chakra-ui",
+        "description": "⚡️ Simple, Modular & Accessible UI Components for your React Applications",
+        "author": "chakra-ui",
+        "author_link": "https://github.com/chakra-ui",
+        "author_avatar": "https://avatars.githubusercontent.com/u/54212428?v=4",
+        "stars": 38073,
+        "topics": [
+            "a11y",
+            "accessible",
+            "ark-ui",
+            "chakra-ui",
+            "component",
+            "css-in-js",
+            "dark-mode",
+            "design-system",
+            "react",
+            "react-components",
+            "reactjs",
+            "styled",
+            "ui-components",
+            "ui-library",
+            "uikit",
+            "wai-aria"
+        ],
+        "license": {
+            "key": "mit",
+            "url": "https://api.github.com/licenses/mit",
+            "name": "MIT License"
+        },
+        "forks": 3285,
+        "open_issues_count": 12,
+        "archived": false,
+        "disabled": false,
+        "original_created_at": "2019-08-17T14:27:54.000Z",
+        "original_updated_at": "2024-12-03T07:58:40.000Z",
+        "created_at": "2024-12-01T14:44:03.981Z",
+        "updated_at": "2024-12-03T10:04:43.429Z",
+        "author_link_madeinnigeria": "https://twitter.com/thesegunadebayo",
+        "author_madeinnigeria": "@thesegunadebayo"
+    }
+]
+}`}
+        
+      
+
+
+
diff --git a/src/lib/pages/docs/page.svelte b/src/lib/pages/docs/page.svelte new file mode 100644 index 0000000..f7ee85d --- /dev/null +++ b/src/lib/pages/docs/page.svelte @@ -0,0 +1,69 @@ + + + +
+ + +
+ {#if state === ''} +
+

Welcome to Naija Stars Docs

+ logo +
+ {:else if state === 'get'} + + {:else if state === 'search'} + + {/if} +
+
+
diff --git a/src/lib/pages/docs/search.svelte b/src/lib/pages/docs/search.svelte new file mode 100644 index 0000000..73af0ba --- /dev/null +++ b/src/lib/pages/docs/search.svelte @@ -0,0 +1,147 @@ +
+
+

Search Repositories

+

Search for Repositories from the database

+ +
+ GET + / v1 / repositories / search +
+ +

Request

+

Query Parameters

+ +
+
+

text

+

+ string +

+
+ +

Search value

+
+
+ +
+
+

curl --request GET \

+

--url https://api.naijastars.dev/v1/repositories/search \

+
+ +
+
+        
+          {`
+            {
+              "data": [
+                {
+                  "id": 34,
+                  "name": "chakra-ui",
+                  "link": "https://github.com/chakra-ui/chakra-ui",
+                  "description": "⚡️ Simple, Modular & Accessible UI Components for your React Applications",
+                  "author": "chakra-ui",
+                  "author_link": "https://github.com/chakra-ui",
+                  "author_avatar": "https://avatars.githubusercontent.com/u/54212428?v=4",
+                  "stars": 38073,
+                  "topics": [
+                      "a11y",
+                      "accessible",
+                      "ark-ui",
+                      "chakra-ui",
+                      "component",
+                      "css-in-js",
+                      "dark-mode",
+                      "design-system",
+                      "react",
+                      "react-components",
+                      "reactjs",
+                      "styled",
+                      "ui-components",
+                      "ui-library",
+                      "uikit",
+                      "wai-aria"
+                  ],
+                  "license": {
+                      "key": "mit",
+                      "url": "https://api.github.com/licenses/mit",
+                      "name": "MIT License"
+                  },
+                  "forks": 3285,
+                  "open_issues_count": 12,
+                  "archived": false,
+                  "disabled": false,
+                  "original_created_at": "2019-08-17T14:27:54.000Z",
+                  "original_updated_at": "2024-12-03T07:58:40.000Z",
+                  "created_at": "2024-12-01T14:44:03.981Z",
+                  "updated_at": "2024-12-03T10:04:43.429Z",
+                  "author_link_madeinnigeria": "https://twitter.com/thesegunadebayo",
+                  "author_madeinnigeria": "@thesegunadebayo"
+              },
+              {
+                  "id": 248,
+                  "name": "zag",
+                  "link": "https://github.com/chakra-ui/zag",
+                  "description": "Finite state machines for building accessible design systems and UI components. Works with modern frameworks, and even just Vanilla JS",
+                  "author": "chakra-ui",
+                  "author_link": "https://github.com/chakra-ui",
+                  "author_avatar": "https://avatars.githubusercontent.com/u/54212428?v=4",
+                  "stars": 4102,
+                  "topics": [
+                      "a11y",
+                      "accessibility",
+                      "agnostic",
+                      "component",
+                      "design-systems",
+                      "headless",
+                      "headlessui",
+                      "library",
+                      "primitives",
+                      "react",
+                      "solid",
+                      "state-machines",
+                      "svelte",
+                      "sveltejs",
+                      "ui",
+                      "ui-components",
+                      "ui-kit",
+                      "universal",
+                      "vue",
+                      "xstate"
+                  ],
+                  "license": {
+                      "key": "mit",
+                      "url": "https://api.github.com/licenses/mit",
+                      "name": "MIT License"
+                  },
+                  "forks": 170,
+                  "open_issues_count": 13,
+                  "archived": false,
+                  "disabled": false,
+                  "original_created_at": "2021-07-07T11:38:07.000Z",
+                  "original_updated_at": "2024-12-03T09:03:41.000Z",
+                  "created_at": "2024-12-01T14:47:25.061Z",
+                  "updated_at": "2024-12-03T10:08:08.882Z",
+                  "author_link_madeinnigeria": "https://twitter.com/thesegunadebayo",
+                  "author_madeinnigeria": "@thesegunadebayo"
+                }
+              ],
+              "search": {
+                  "text": "chakra",
+                  "totalItems": 2
+              }
+            }
+          `}
+        
+      
+
+
+
diff --git a/src/lib/pages/home/page.svelte b/src/lib/pages/home/page.svelte index e2c7e1d..09bb8db 100644 --- a/src/lib/pages/home/page.svelte +++ b/src/lib/pages/home/page.svelte @@ -1,8 +1,11 @@ -
- {#if isFetching && !isMounted} -
-
- - - - - - +
+ + +
+ {#if isFetching && !isMounted} +
+
+ + + + + + +
+
+ {:else} +
+

+ Open source projects in Nigeria +

-
- {:else} -
-

- Open source projects in Nigeria -

-
- {#key gettingFreshData} -
- {/key} - {/if} + {#key gettingFreshData} +
+ {/key} + {/if} + diff --git a/src/lib/pages/home/table.svelte b/src/lib/pages/home/table.svelte index 6b78d89..60b9a50 100644 --- a/src/lib/pages/home/table.svelte +++ b/src/lib/pages/home/table.svelte @@ -1,16 +1,14 @@
-
+
+ +
+ {#each $headerRows as headerRow} @@ -195,18 +180,21 @@ {...attrs} class={cn('[&:has([role=checkbox])]:pl-3')} > - {#if cell.id === 'stars'} + {#if cell.id === 'stars' || cell.id === 'forks'} {:else} @@ -222,20 +210,29 @@ {#each $pageRows as row (row.id)} - + {#each row.cells as cell (cell.id)} - {#if cell.id === 'amount'} -
- -
- {:else if cell.id === 'status'} -
- + {#if cell.id === 'link'} + + + + + {:else if cell.id === 'author_avatar'} +
+
{:else} @@ -249,44 +246,47 @@
-
+
- {$rows.length} repo(s) | Page {currentPage} of + {$rows.length} repo(s) | Page {apiMetadata.pagination.currentPage} of {apiMetadata.pagination.totalPages}
- +
+ - - - + + + +
diff --git a/src/lib/pages/other/page.svelte b/src/lib/pages/other/page.svelte index 7130a90..b303895 100644 --- a/src/lib/pages/other/page.svelte +++ b/src/lib/pages/other/page.svelte @@ -1,9 +1,16 @@ -
-
- +
+ + +
+
+ +
diff --git a/src/lib/pages/shared/sidebar.svelte b/src/lib/pages/shared/sidebar.svelte new file mode 100644 index 0000000..111099b --- /dev/null +++ b/src/lib/pages/shared/sidebar.svelte @@ -0,0 +1,56 @@ + + + diff --git a/src/lib/types/repository.ts b/src/lib/types/repository.ts index 7ce0f8e..bf701be 100644 --- a/src/lib/types/repository.ts +++ b/src/lib/types/repository.ts @@ -36,7 +36,7 @@ export type ApiMetadata = { hasPrevPage: boolean; }; sort: { - sortBy: 'stars' | 'author'; + sortBy: 'stars' | 'author' | 'forks'; order: 'asc' | 'desc'; }; }; diff --git a/src/style.css b/src/style.css index 75cceba..93940ef 100644 --- a/src/style.css +++ b/src/style.css @@ -87,3 +87,21 @@ padding-right: 2rem; padding-left: 2rem; } +@media (max-width: 640px) { + .container { + padding-right: 0.5rem; + padding-left: 0.5rem; + } +} + +.pre code { + white-space: pre-wrap; + word-wrap: break-word; + font-family: monospace; +} + +.bg-black pre { + max-width: 100%; + overflow-x: auto; + padding: 1rem; +}