Skip to content

Commit c4facd8

Browse files
committed
Merge branch 'trpc-react-node-crud'
2 parents 86f99a8 + 67b2b88 commit c4facd8

38 files changed

+4970
-2416
lines changed

packages/client/package.json

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,33 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6-
"@hookform/resolvers": "^2.9.3",
7-
"@testing-library/jest-dom": "^5.16.4",
8-
"@testing-library/react": "^13.3.0",
9-
"@testing-library/user-event": "^13.5.0",
10-
"@trpc/client": "^9.25.3",
11-
"@trpc/react": "^9.25.3",
12-
"@types/jest": "^27.5.2",
13-
"@types/node": "^16.11.41",
14-
"@types/react": "^18.0.14",
15-
"@types/react-dom": "^18.0.5",
6+
"@hookform/resolvers": "^2.9.10",
7+
"@tanstack/react-query": "^4.13.0",
8+
"@tanstack/react-query-devtools": "^4.13.0",
9+
"@testing-library/jest-dom": "^5.16.5",
10+
"@testing-library/react": "^13.4.0",
11+
"@testing-library/user-event": "^14.4.3",
12+
"@trpc/client": "^10.0.0-proxy-beta.26",
13+
"@trpc/react": "^9.27.4",
14+
"@trpc/react-query": "^10.0.0-proxy-beta.26",
15+
"@trpc/server": "^10.0.0-proxy-beta.26",
16+
"@types/jest": "^29.2.0",
17+
"@types/node": "^18.11.6",
18+
"@types/react": "^18.0.23",
19+
"@types/react-dom": "^18.0.7",
1620
"react": "^18.2.0",
1721
"react-cookie": "^4.1.1",
1822
"react-dom": "^18.2.0",
19-
"react-hook-form": "^7.33.0",
20-
"react-query": "^3.39.1",
21-
"react-router-dom": "^6.3.0",
23+
"react-hook-form": "^7.38.0",
24+
"react-router-dom": "^6.4.2",
2225
"react-scripts": "5.0.1",
23-
"react-toastify": "^9.0.5",
24-
"server": "1.0.0",
25-
"typescript": "^4.7.4",
26-
"web-vitals": "^2.1.4",
27-
"zod": "^3.17.3"
26+
"react-toastify": "^9.0.8",
27+
"server": "^1.0.37",
28+
"tailwind-merge": "^1.7.0",
29+
"typescript": "^4.8.4",
30+
"web-vitals": "^3.0.4",
31+
"zod": "^3.19.1",
32+
"zustand": "^4.1.3"
2833
},
2934
"scripts": {
3035
"start": "react-scripts start",
@@ -51,8 +56,8 @@
5156
]
5257
},
5358
"devDependencies": {
54-
"autoprefixer": "^10.4.7",
55-
"postcss": "^8.4.14",
56-
"tailwindcss": "^3.1.4"
59+
"autoprefixer": "^10.4.12",
60+
"postcss": "^8.4.18",
61+
"tailwindcss": "^3.2.1"
5762
}
5863
}

packages/client/public/index.html

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,16 @@
1010
content="Web site created using create-react-app"
1111
/>
1212
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
13-
<!--
14-
manifest.json provides metadata used when your web app is installed on a
15-
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
16-
-->
1713
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
18-
<!--
19-
Notice the use of %PUBLIC_URL% in the tags above.
20-
It will be replaced with the URL of the `public` folder during the build.
21-
Only files inside the `public` folder can be referenced from the HTML.
22-
23-
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
24-
work correctly both with client-side routing and a non-root public URL.
25-
Learn how to configure a non-root public URL by running `npm run build`.
26-
-->
14+
<link
15+
href="https://unpkg.com/boxicons@2.1.2/css/boxicons.min.css"
16+
rel="stylesheet"
17+
/>
2718
<title>React App</title>
2819
</head>
2920
<body>
3021
<noscript>You need to enable JavaScript to run this app.</noscript>
3122
<div id="root"></div>
32-
<!--
33-
This HTML file is a template.
34-
If you open it directly in the browser, you will see an empty page.
35-
36-
You can add webfonts, meta tags, or analytics to this file.
37-
The build step will place the bundled scripts into the <body> tag.
38-
39-
To begin the development, run `npm start` or `yarn start`.
40-
To create a production bundle, use `npm run build` or `yarn build`.
41-
-->
23+
<div id="post-modal"></div>
4224
</body>
4325
</html>

packages/client/src/App.tsx

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import { useState } from 'react';
2-
import { QueryClientProvider, QueryClient } from 'react-query';
3-
import { ReactQueryDevtools } from 'react-query/devtools';
4-
import { useRoutes } from 'react-router-dom';
5-
import { getFetch } from '@trpc/client';
6-
import routes from './router';
7-
import { trpc } from './trpc';
8-
import AuthMiddleware from './middleware/AuthMiddleware';
1+
import { useState } from "react";
2+
import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
3+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
4+
import { useRoutes } from "react-router-dom";
5+
import { getFetch, httpBatchLink, loggerLink } from "@trpc/client";
6+
import routes from "./router";
7+
import { trpc } from "./trpc";
8+
import AuthMiddleware from "./middleware/AuthMiddleware";
9+
import { CookiesProvider } from "react-cookie";
910

1011
function AppContent() {
1112
const content = useRoutes(routes);
@@ -23,27 +24,35 @@ function App() {
2324
},
2425
})
2526
);
27+
2628
const [trpcClient] = useState(() =>
2729
trpc.createClient({
28-
url: 'http://localhost:8000/api/trpc',
29-
fetch: async (input, init?) => {
30-
const fetch = getFetch();
31-
return fetch(input, {
32-
...init,
33-
credentials: 'include',
34-
});
35-
},
30+
links: [
31+
loggerLink(),
32+
httpBatchLink({
33+
url: "http://localhost:8000/api/trpc",
34+
fetch: async (input, init?) => {
35+
const fetch = getFetch();
36+
return fetch(input, {
37+
...init,
38+
credentials: "include",
39+
});
40+
},
41+
}),
42+
],
3643
})
3744
);
3845
return (
39-
<trpc.Provider client={trpcClient} queryClient={queryClient}>
40-
<QueryClientProvider client={queryClient}>
41-
<AuthMiddleware>
42-
<AppContent />
43-
</AuthMiddleware>
44-
<ReactQueryDevtools initialIsOpen={false} />
45-
</QueryClientProvider>
46-
</trpc.Provider>
46+
<CookiesProvider>
47+
<trpc.Provider client={trpcClient} queryClient={queryClient}>
48+
<QueryClientProvider client={queryClient}>
49+
<AuthMiddleware>
50+
<AppContent />
51+
</AuthMiddleware>
52+
<ReactQueryDevtools initialIsOpen={false} />
53+
</QueryClientProvider>
54+
</trpc.Provider>
55+
</CookiesProvider>
4756
);
4857
}
4958

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import React, { useCallback } from 'react';
2+
import { Controller, useController, useFormContext } from 'react-hook-form';
3+
import useStore from '../store';
4+
import Spinner from './Spinner';
5+
6+
type FileUpLoaderProps = {
7+
name: string;
8+
};
9+
const FileUpLoader: React.FC<FileUpLoaderProps> = ({ name }) => {
10+
const {
11+
control,
12+
formState: { errors },
13+
} = useFormContext();
14+
const { field } = useController({ name, control });
15+
const store = useStore();
16+
17+
const onFileDrop = useCallback(
18+
async (e: React.SyntheticEvent<EventTarget>) => {
19+
const target = e.target as HTMLInputElement;
20+
if (!target.files || target.files.length === 0) return;
21+
const newFile = Object.values(target.files).map((file: File) => file);
22+
const formData = new FormData();
23+
formData.append('file', newFile[0]);
24+
formData.append('upload_preset', 'trpc-api');
25+
26+
store.setUploadingImage(true);
27+
const data = await fetch(
28+
'https://api.cloudinary.com/v1_1/Codevo/image/upload',
29+
{
30+
method: 'POST',
31+
body: formData,
32+
}
33+
)
34+
.then((res) => {
35+
store.setUploadingImage(false);
36+
37+
return res.json();
38+
})
39+
.catch((err) => {
40+
store.setUploadingImage(false);
41+
console.log(err);
42+
});
43+
44+
if (data.secure_url) {
45+
field.onChange(data.secure_url);
46+
}
47+
},
48+
49+
[field, store]
50+
);
51+
52+
return (
53+
<Controller
54+
name={name}
55+
defaultValue=''
56+
control={control}
57+
render={({ field: { name, onBlur, ref } }) => (
58+
<>
59+
<div className='mb-2 flex justify-between items-center'>
60+
<div>
61+
<span className='block mb-2'>Choose profile photo</span>
62+
<input
63+
className='block text-sm mb-2 text-slate-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-violet-50 file:text-violet-700 hover:file:bg-violet-100'
64+
type='file'
65+
name={name}
66+
onBlur={onBlur}
67+
ref={ref}
68+
onChange={onFileDrop}
69+
multiple={false}
70+
accept='image/jpg, image/png, image/jpeg'
71+
/>
72+
</div>
73+
<div>
74+
{store.uploadingImage && <Spinner color='text-yellow-400' />}
75+
</div>
76+
</div>
77+
<p
78+
className={`text-red-500 text-xs italic mb-2 ${
79+
errors[name] ? 'visible' : 'invisible'
80+
}`}
81+
>
82+
{errors[name] && (errors[name]?.message as string)}
83+
</p>
84+
</>
85+
)}
86+
/>
87+
);
88+
};
89+
90+
export default FileUpLoader;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy