Skip to content

WORK IN PROGRESS - init nextjs UI renewal #103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/nextjs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
on: [push]

name: "CI Node"

jobs:
test:
name: Test

runs-on: ubuntu-latest

strategy:
matrix:
node-versions: [16, 18]

steps:
- name: Checkout
uses: actions/checkout@v2

- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-versions }}

- name: NPM Install
working-directory: ./ui
run: npm install

- name: Build, lint and export
working-directory: ./ui
run: npm run export



2 changes: 1 addition & 1 deletion .github/workflows/phptest.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
on: [push]

name: "CI"
name: "CI PHP"

jobs:
test:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ node_modules
.php-cs-fixer.cache
.DS_Store
_ide_helper.php
dist
1 change: 0 additions & 1 deletion resources/dist/app.js

This file was deleted.

760 changes: 1 addition & 759 deletions resources/views/index.blade.php

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions src/Controllers/LaravelRequestDocsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ public function index(Request $request)
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
);
}
if ($request->json) {
return response()->json(
$docs,
Response::HTTP_OK,
[
'Content-type'=> 'application/json; charset=utf-8'
],
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
);
}
// nextjs static page rendered via blade
return view('request-docs::index')->with(compact('docs'));
}
}
13 changes: 13 additions & 0 deletions ui/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": [
"next/core-web-vitals",
"plugin:react/recommended",
"plugin:react-hooks/recommended"
],
"rules": {
"jsx-quotes": ["warn", "prefer-double"],
"quotes": ["warn", "double"],
"semi": ["warn", "never"],
"react/prop-types": ["error", { "ignore": ["children", "className"] }]
}
}
36 changes: 36 additions & 0 deletions ui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
4 changes: 4 additions & 0 deletions ui/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
34 changes: 34 additions & 0 deletions ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
7 changes: 7 additions & 0 deletions ui/app/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"use client"

import React from "react"

export default function Error() {
return <h1>Error</h1>
}
12 changes: 12 additions & 0 deletions ui/app/head.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Script from "next/script"
import React from "react"

export default function Head({ params }: { params: { slug: string } }) {
return (
<>
<title>Laravel Request Docs</title>
<link rel="icon" type="image/x-icon" href={`${process.env.NEXT_PUBLIC_BASE_PATH}/lrd.png`} />
{/* <Script src={`${process.env.NEXT_PUBLIC_BASE_PATH}/scripts/observer.js`} type="text/javascript" /> */}
</>
)
}
25 changes: 25 additions & 0 deletions ui/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from "react"
import { FontSans, FontMono } from "../components/DefaultFonts"
import GlobalState from "../components/GlobalState"

import NavBar from "../components/NavBar"

import "../styles/globals.css"


export default async function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<GlobalState>
<html className="antialiased">
<body className={`${FontSans.variable} ${FontMono.variable} font-sans h-100vh`}>
<NavBar />
{children}
</body>
</html>
</GlobalState>
)
}
77 changes: 77 additions & 0 deletions ui/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"use client"

import React, { createRef, useEffect, useState } from "react"
import SideBar from "../components/SideBar"
import APICard from "../components/APICard"
import { getAPIInfoId } from "../utils/utils"

async function getData(): Promise<IAPIInfo[]> {
try {
const response = await fetch("http://localhost:3000/vendor/request-docs/api/sample")
return response.json()
} catch (error) {
console.error(error)
return []
}
}

function useAPIInfoData(): IAPIInfo[] {
const [apiInfoData, setAPIInfoData] = useState<IAPIInfo[]>([])
useEffect(() => {
async function setData() {
const data = await getData()
setAPIInfoData(data)
}
setData()
}, [])
return apiInfoData
}

export default function Index() {
const data = useAPIInfoData()
const [activeItemID, setActiveItemID] = useState(getAPIInfoId(data[0]))
const baseURL = process.env.NEXT_PUBLIC_BASE_URL ||
(typeof window !== "undefined") ? `${window.location.protocol}//${window.location.host}` : ""

const refs = data.reduce((refsObj, item) => {
refsObj[getAPIInfoId(item)] = createRef<HTMLElement>()
return refsObj
}, {} as { [key: string]: React.RefObject<HTMLElement> })

const handleClick = (id: string) => {
refs[id].current?.scrollIntoView({
behavior: "smooth",
block: "center",
})
if (typeof window !== "undefined") window.location.hash = id
}

return (
<div className="mt-2" id="main-container">
<div className="drawer drawer-mobile">
<input id="side-bar-drawer" type="checkbox" className="drawer-toggle" />
<div className="drawer-content flex flex-col items-center bg-base-100 ml-4 scroll-smooth">
<label htmlFor="side-bar-drawer" className="btn btn-primary drawer-button lg:hidden">Open drawer</label>
<main className="w-full">
<div className="mx-auto">
{data.map((item) => (
<APICard
key={getAPIInfoId(item)}
item={item}
refs={refs}
activeItemID={activeItemID}
setActiveItemID={setActiveItemID}
baseURL={baseURL}
/>
))}
</div>
</main>
</div>
<div className="drawer-side bg-base-100">
<label htmlFor="side-bar-drawer" className="drawer-overlay"></label>
<SideBar data={data} handleClick={handleClick} activeItemID={activeItemID} />
</div>
</div>
</div>
)
}
82 changes: 82 additions & 0 deletions ui/components/APICard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"use client"

import React, { RefObject, useEffect } from "react"
import { useRouter } from "next/navigation"
import { getAPIInfoId } from "@/utils/utils"
import APIDocBlock from "./APIDocBlock"
import APIParamTable from "./APIParamTable"
import APIRefTable from "./APIRefTable"
import APITryBlock from "./APITryBlock"

export interface APICardProps {
item: IAPIInfo;
baseURL: string;
activeItemID?: string;
setActiveItemID: (id: string) => void;
refs: { [key: string]: RefObject<HTMLElement> };
}

const apiMethodColor: { [key: string]: string[] } = {
GET: ["text-info"],
POST: ["text-success"],
PUT: ["text-warning"],
PATCH: ["text-warning"],
DELETE: ["text-error"],
HEAD: ["text-info"],
}


export default function APICard({ item, activeItemID, setActiveItemID, refs, baseURL }: APICardProps) {
const ruleList = Object.keys(item.rules)
const elementID = getAPIInfoId(item)
const router = useRouter()

// Auto change URI & highlight NavItems on scroll
useEffect(() => {
const observerConfig = {
rootMargin: "-5% 0px -95% 0px",
threshold: [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
}
const handleIntersection = (entries: IntersectionObserverEntry[]) => {
entries.forEach((entry) => {
if (entry.target.id !== activeItemID && entry.isIntersecting) {
setActiveItemID(entry.target.id)
}

})
}
const observer = new IntersectionObserver(
handleIntersection,
observerConfig)
if(refs[elementID].current) observer.observe(refs[elementID].current as HTMLElement)
return () => observer.disconnect() // Cleanup the observer if component unmount.
}, [activeItemID, elementID, refs, setActiveItemID])

return (
<section
data-scrollspy
ref={refs[elementID]}
id={elementID}
className="api-card ml-2 mr-10 my-6 divide-y divide-base-content/20 overflow-hidden rounded-lg bg-base-100 border border-base-content/10 group/api-card focus:border-primary">
<div className="flex flex-col p-8 gap-2">
<h2 className="flex items-center gap-2 font-semibold text-xl">
<span className="flex flex-row hover:font-semibold hover:bg-inherit items-center">
<span className={`${apiMethodColor[item.httpMethod]?.join(" ")} uppercase text-sm w-fit pr-2 flex flex-row mt-0.5`}>{item.httpMethod}</span>
<span className="flex-1 p-0 text-md items-center">{item.uri}</span>
</span>
</h2>
<APIDocBlock>{item.docBlock}</APIDocBlock>
<APIRefTable
controller={item.controller_full_path}
method={item.method}
middlewares={item.middlewares}
/>
{ruleList.length > 0 ? (
<APIParamTable params={item.rules} />
) : null}
<APITryBlock item={item} baseURL={baseURL} />
</div>
</section>

)
}
18 changes: 18 additions & 0 deletions ui/components/APICode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from "react"

export function APIRequest() {
return (
<div className="py-3">
<div className="mockup-code">
<pre data-prefix="$">
<code>curl https://api.laravel-request-docs.com/v1/sample</code>
</pre>
</div>
</div>
)
}


export function APIResponse() {

}
Loading