Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita893cf5

Browse files
committed
updated
1 parent0a0f1fe commita893cf5

File tree

13 files changed

+182
-84
lines changed

13 files changed

+182
-84
lines changed

‎packages/client/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@
2222
"react-scripts":"5.0.1",
2323
"react-toastify":"^9.0.5",
2424
"server":"1.0.0",
25+
"tailwind-merge":"^1.3.0",
2526
"typescript":"^4.7.4",
2627
"web-vitals":"^2.1.4",
27-
"zod":"^3.17.3"
28+
"zod":"^3.17.3",
29+
"zustand":"^4.0.0-rc.1"
2830
},
2931
"scripts": {
3032
"start":"react-scripts start",
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
importReact,{useCallback}from'react';
2+
import{Controller,useController,useFormContext}from'react-hook-form';
3+
importuseStorefrom'../store';
4+
importSpinnerfrom'./Spinner';
5+
6+
typeFileUpLoaderProps={
7+
name:string;
8+
};
9+
constFileUpLoader:React.FC<FileUpLoaderProps>=({ name})=>{
10+
const{
11+
control,
12+
formState:{ errors},
13+
}=useFormContext();
14+
const{ field}=useController({ name, control});
15+
conststore=useStore();
16+
17+
constonFileDrop=useCallback(
18+
async(e:React.SyntheticEvent<EventTarget>)=>{
19+
consttarget=e.targetasHTMLInputElement;
20+
if(!target.files)return;
21+
constnewFile=Object.values(target.files).map((file:File)=>file);
22+
constformData=newFormData();
23+
formData.append('file',newFile[0]);
24+
formData.append('upload_preset','trpc-api');
25+
26+
store.setUploadingImage(true);
27+
constdata=awaitfetch(
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+
returnres.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+
<divclassName='mb-2 flex justify-between items-center'>
60+
<div>
61+
<spanclassName='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&&<Spinnercolor='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]?.messageasstring)}
83+
</p>
84+
</>
85+
)}
86+
/>
87+
);
88+
};
89+
90+
exportdefaultFileUpLoader;

‎packages/client/src/components/Header.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import{useQueryClient}from'react-query';
22
import{Link}from'react-router-dom';
3-
import{useStateContext}from'../context';
3+
importuseStorefrom'../store';
44
import{trpc}from'../trpc';
55

66
constHeader=()=>{
7-
conststateContext=useStateContext();
8-
constuser=stateContext.state.authUser;
7+
conststore=useStore();
8+
constuser=store.authUser;
99

1010
constqueryClient=useQueryClient();
1111
const{mutate:logoutUser}=trpc.useMutation(['auth.logout'],{
@@ -14,7 +14,6 @@ const Header = () => {
1414
document.location.href='/login';
1515
},
1616
onError(error){
17-
console.log(error);
1817
queryClient.clear();
1918
document.location.href='/login';
2019
},

‎packages/client/src/components/Spinner.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
importReactfrom'react';
2+
import{twMerge}from'tailwind-merge';
23
typeSpinnerProps={
34
width?:number;
45
height?:number;
6+
color?:string;
7+
bgColor?:string;
58
};
6-
constSpinner:React.FC<SpinnerProps>=({ width=5, height=5})=>{
9+
constSpinner:React.FC<SpinnerProps>=({
10+
width=5,
11+
height=5,
12+
color,
13+
bgColor,
14+
})=>{
715
return(
816
<svg
917
role='status'
10-
className={`w-5 h-5 mr-2 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600`}
18+
className={twMerge(
19+
'w-5 h-5 mr-2 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600',
20+
`w-${width} h-${height}${color}${bgColor}`
21+
)}
1122
viewBox='0 0 100 101'
1223
fill='none'
1324
xmlns='http://www.w3.org/2000/svg'

‎packages/client/src/components/requireUser.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import{useCookies}from'react-cookie';
22
import{Navigate,Outlet,useLocation}from'react-router-dom';
3-
import{useStateContext}from'../context';
4-
import{IUser}from'../context/types';
3+
import{IUser}from'../libs/types';
4+
importuseStorefrom'../store';
55
import{trpc}from'../trpc';
66
importFullScreenLoaderfrom'./FullScreenLoader';
77

88
constRequireUser=({ allowedRoles}:{allowedRoles:string[]})=>{
99
const[cookies]=useCookies(['logged_in']);
1010
constlocation=useLocation();
11-
conststateContext=useStateContext();
11+
conststore=useStore();
1212

1313
const{
1414
isLoading,
@@ -18,7 +18,7 @@ const RequireUser = ({ allowedRoles }: { allowedRoles: string[] }) => {
1818
retry:1,
1919
select:(data)=>data.data.user,
2020
onSuccess:(data)=>{
21-
stateContext.dispatch({type:'SET_USER',payload:dataasIUser});
21+
store.setAuthUser(dataasIUser);
2222
},
2323
onError:(error)=>{
2424
console.log(error);

‎packages/client/src/context/index.tsx

Lines changed: 0 additions & 57 deletions
This file was deleted.

‎packages/client/src/index.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import ReactDOM from 'react-dom/client';
33
import{BrowserRouterasRouter}from'react-router-dom';
44
import{ToastContainer}from'react-toastify';
55
importAppfrom'./App';
6-
import{StateContextProvider}from'./context';
6+
77
import'./global.css';
88
import'react-toastify/dist/ReactToastify.css';
99

@@ -12,11 +12,9 @@ const root = ReactDOM.createRoot(
1212
);
1313
root.render(
1414
<React.StrictMode>
15-
<StateContextProvider>
16-
<Router>
17-
<App/>
18-
<ToastContainer/>
19-
</Router>
20-
</StateContextProvider>
15+
<Router>
16+
<App/>
17+
<ToastContainer/>
18+
</Router>
2119
</React.StrictMode>
2220
);

‎packages/client/src/context/types.tsrenamed to‎packages/client/src/libs/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export interface IUser {
55
photo:string;
66
_id:string;
77
id:string;
8-
created_at:string;
9-
updated_at:string;
8+
createdAt:string;
9+
updatedAt:string;
1010
__v:number;
1111
}

‎packages/client/src/middleware/AuthMiddleware.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import{useCookies}from'react-cookie';
2-
import{useStateContext}from'../context';
32
importFullScreenLoaderfrom'../components/FullScreenLoader';
43
importReactfrom'react';
54
import{trpc}from'../trpc';
6-
import{IUser}from'../context/types';
5+
import{IUser}from'../libs/types';
76
import{useQueryClient}from'react-query';
7+
importuseStorefrom'../store';
88

99
typeAuthMiddlewareProps={
1010
children:React.ReactElement;
1111
};
1212

1313
constAuthMiddleware:React.FC<AuthMiddlewareProps>=({ children})=>{
1414
const[cookies]=useCookies(['logged_in']);
15-
conststateContext=useStateContext();
15+
conststore=useStore();
1616

1717
constqueryClient=useQueryClient();
1818
const{ refetch}=trpc.useQuery(['auth.refresh'],{
@@ -28,7 +28,7 @@ const AuthMiddleware: React.FC<AuthMiddlewareProps> = ({ children }) => {
2828
retry:1,
2929
select:(data)=>data.data.user,
3030
onSuccess:(data)=>{
31-
stateContext.dispatch({type:'SET_USER',payload:dataasIUser});
31+
store.setAuthUser(dataasIUser);
3232
},
3333
onError:(error)=>{
3434
letretryRequest=true;

‎packages/client/src/pages/profile.page.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import{useStateContext}from'../context';
1+
importuseStorefrom'../store';
22

33
constProfilePage=()=>{
4-
conststateContext=useStateContext();
4+
conststore=useStore();
55

6-
constuser=stateContext.state.authUser;
6+
constuser=store.authUser;
77

88
return(
99
<sectionclassName='bg-ct-blue-600 min-h-screen pt-20'>

‎packages/client/src/pages/register.page.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import FormInput from '../components/FormInput';
77
import{LoadingButton}from'../components/LoadingButton';
88
import{toast}from'react-toastify';
99
import{trpc}from'../trpc';
10+
importFileUpLoaderfrom'../components/FileUpload';
1011

1112
constregisterSchema=object({
1213
name:string().min(1,'Full name is required').max(100),
1314
email:string()
1415
.min(1,'Email address is required')
1516
.email('Email Address is invalid'),
17+
photo:string().min(1,'Photo is required').url('Photo URL is invalid'),
1618
password:string()
1719
.min(1,'Password is required')
1820
.min(8,'Password must be more than 8 characters')
@@ -88,6 +90,7 @@ const RegisterPage = () => {
8890
name='passwordConfirm'
8991
type='password'
9092
/>
93+
<FileUpLoadername='photo'/>
9194
<spanclassName='block'>
9295
Already have an account?{' '}
9396
<Linkto='/login'className='text-ct-blue-600'>

‎packages/client/src/store/index.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
importcreatefrom'zustand';
2+
import{IUser}from'../libs/types';
3+
4+
typeStore={
5+
authUser:IUser|null;
6+
uploadingImage:boolean;
7+
pageLoading:boolean;
8+
openModal:boolean;
9+
setAuthUser:(user:IUser)=>void;
10+
setUploadingImage:(isUploading:boolean)=>void;
11+
setPageLoading:(isLoading:boolean)=>void;
12+
setOpenModal:(isOpen:boolean)=>void;
13+
};
14+
15+
constuseStore=create<Store>((set)=>({
16+
authUser:null,
17+
uploadingImage:false,
18+
pageLoading:false,
19+
openModal:false,
20+
setAuthUser:(user)=>set((state)=>({ ...state,authUser:user})),
21+
setUploadingImage:(isUploading)=>
22+
set((state)=>({ ...state,uploadingImage:isUploading})),
23+
setPageLoading:(isLoading)=>
24+
set((state)=>({ ...state,pageLoading:isLoading})),
25+
setOpenModal:(isOpen)=>set((state)=>({ ...state,openModal:isOpen})),
26+
}));
27+
28+
exportdefaultuseStore;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp