Browse Source

Add frontend and backend integration example

adi-git-demo-rebase
Adi Thakral 1 year ago
parent
commit
08fc9eb3ab
  1. 12
      .vscode/settings.json
  2. 2
      assets/client-server-interaction.drawio
  3. 2
      assets/client-server-interaction.svg
  4. 2
      backend/main.py
  5. 29
      frontend/next.config.js
  6. 3
      frontend/pages/hello-world.json
  7. 48
      frontend/pages/hello-world.tsx
  8. 4
      frontend/utils/api.ts

12
.vscode/settings.json vendored

@ -2,6 +2,18 @@
"typescript.tsdk": "frontend/node_modules/typescript/lib",
"eslint.format.enable": true,
"eslint.codeActionsOnSave.mode": "all",
"[javascript]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"[javascriptreact]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"[typescript]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {

2
assets/client-server-interaction.drawio

@ -1 +1 @@
<mxfile host="www.draw.io" modified="2021-03-15T04:26:06.589Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36" etag="t9BACponPf5-u58TPj24" version="14.4.8" type="device"><diagram id="nWxgDZutG5X04Ajf33Mw" name="Page-1">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</diagram></mxfile>
<mxfile host="app.diagrams.net" modified="2021-03-15T06:55:32.703Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36" etag="CQUO9gWHRxDxe8Ce6UdG" version="14.4.8" type="device"><diagram id="nWxgDZutG5X04Ajf33Mw" name="Page-1">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</diagram></mxfile>

2
assets/client-server-interaction.svg

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

2
backend/main.py

@ -8,7 +8,7 @@ DB_PATH = os.path.join(os.path.dirname(__file__), 'links.db')
@app.route('/')
def hello_world():
return 'Hello, World!'
return 'Hello from backend!'
def regen_JSON():
"""Gets links from DB and outputs them in JSON"""

29
frontend/next.config.js

@ -0,0 +1,29 @@
// @ts-check
/* eslint-disable @typescript-eslint/no-var-requires */
// eslint-disable-next-line no-undef
const { PHASE_DEVELOPMENT_SERVER } = require("next/constants");
const devConfig = {
async rewrites() {
return [
{
source: "/api",
destination: "http://localhost:5000",
},
{
source: "/api/:slug",
destination: "http://localhost:5000/:slug",
},
];
},
};
const prodConfig = {
basePath: "/links",
};
// eslint-disable-next-line no-undef
module.exports = (phase) =>
phase === PHASE_DEVELOPMENT_SERVER ? devConfig : prodConfig;

3
frontend/pages/hello-world.json

@ -0,0 +1,3 @@
{
"greeting": "Hello from JSON"
}

48
frontend/pages/hello-world.tsx

@ -0,0 +1,48 @@
import React from "react";
import { GetStaticProps } from "next";
import GreetingJSON from "./hello-world.json";
import { fetchExample } from "utils/api";
interface Props {
greeting: string;
}
export const getStaticProps: GetStaticProps<Props> = async () => {
return {
props: { greeting: GreetingJSON.greeting }, // will be passed to the page component as props
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every second
revalidate: 1,
};
};
function HelloWorld({ greeting }: Props): JSX.Element {
const [greetings, setGreetings] = React.useState([greeting]);
const getMoreGreetings = async () => {
const greetingFromBackend = await fetchExample();
setGreetings([
...greetings,
`"${greetingFromBackend}" --- ${new Date().toISOString()}`,
]);
};
return (
<div style={{ padding: "50px" }}>
<button
style={{ border: "2px solid black", padding: "5px" }}
onClick={getMoreGreetings}
>
Get greeting from the server
</button>
<ol style={{ listStyleType: "decimal" }}>
{greetings.map((greeting) => (
<li key={greeting}>{greeting}</li>
))}
</ol>
</div>
);
}
export default HelloWorld;

4
frontend/utils/api.ts

@ -0,0 +1,4 @@
export async function fetchExample(): Promise<string> {
const response = await fetch("/api");
return await response.text();
}
Loading…
Cancel
Save