1
1
import type { ActionFunction } from "@remix-run/node" ;
2
- import { json , redirect } from "@remix-run/node" ;
3
2
import { Form , useActionData } from "@remix-run/react" ;
4
3
import * as React from "react" ;
5
4
6
- import { requireUserId } from "~/session.server" ;
7
5
8
6
import {
9
7
// When using a local executable shema (avoids an HTTP roundtrip)
@@ -14,8 +12,7 @@ import {
14
12
15
13
type ActionData = {
16
14
errors ?: {
17
- title ?: string ;
18
- body ?: string ;
15
+ name ?: string ;
19
16
} ;
20
17
} ;
21
18
@@ -30,14 +27,61 @@ mutation Insert_users($objects: [users_insert_input!]!) {
30
27
}
31
28
` ;
32
29
30
+ // TODO: check how we can pick the mutation depending on the "update" or "create" scenario
31
+ /**
32
+ /*
33
+ {
34
+ "where": {
35
+ "id": {
36
+ "_eq": "e77584bb-3301-42b6-b952-297170cb8bc8"
37
+ }
38
+ },
39
+ "set": {
40
+ "name": "Eric Burel v2"
41
+ }
42
+ }*/
43
+ const UPDATE_USER_MUTATION = /* GraphQL */ `
44
+ mutation Update_users($where: users_bool_exp!, $set: users_set_input) {
45
+ update_users(where: $where, _set: $set) {
46
+ returning {
47
+ id
48
+ name
49
+ }
50
+ }
51
+ }
52
+ `
53
+
54
+ /**
55
+ * {
56
+ "deleteUsersWhere": {
57
+ "id": {
58
+ "_eq": ""
59
+ }
60
+ }
61
+ }
62
+ */
63
+ const DELETE_USER_MUTATION = /* GraphQL */ `
64
+ mutation Delete_users($deleteUsersWhere: users_bool_exp!) {
65
+ delete_users(where: $deleteUsersWhere) {
66
+ returning {
67
+ name
68
+ }
69
+ }
70
+ }
71
+ `
72
+
73
+
33
74
// The `processRequestWithGraphQL` function can be used for both loaders and
34
75
// actions!
35
- export const action : ActionFunction = ( args ) =>
76
+ export const action : ActionFunction = ( args : any ) =>
77
+ // TODO: how to handle multiple actions?
78
+ // if (update)
36
79
sendGraphQLRequest ( {
37
80
args,
38
81
// Space X API is one of the few to allow mutations
39
82
// @see https://studio.apollographql.com/public/SpaceX-pxxbxen/home?variant=current
40
83
endpoint : "https://api.spacex.land/graphql/" ,
84
+ // TODO: get from args?
41
85
variables : {
42
86
"objects" : [
43
87
{ "name" : "Eric Burel" }
@@ -46,115 +90,45 @@ export const action: ActionFunction = (args) =>
46
90
//schema,
47
91
query : INSERT_USER_MUTATION
48
92
} ) ;
93
+ // else
49
94
50
- export default function NewNotePage ( ) {
51
- const actionData = useActionData ( ) as ActionData ;
52
- const titleRef = React . useRef < HTMLInputElement > ( null ) ;
53
- const bodyRef = React . useRef < HTMLTextAreaElement > ( null ) ;
54
-
55
- React . useEffect ( ( ) => {
56
- if ( actionData ?. errors ?. title ) {
57
- titleRef . current ?. focus ( ) ;
58
- } else if ( actionData ?. errors ?. body ) {
59
- bodyRef . current ?. focus ( ) ;
60
- }
61
- } , [ actionData ] ) ;
62
-
63
- return (
64
- < Form
65
- method = "post"
66
- style = { {
67
- display : "flex" ,
68
- flexDirection : "column" ,
69
- gap : 8 ,
70
- width : "100%" ,
71
- } }
72
- >
73
- < div >
74
- < label className = "flex w-full flex-col gap-1" >
75
- < span > Title: </ span >
76
- < input
77
- ref = { titleRef }
78
- name = "title"
79
- className = "flex-1 rounded-md border-2 border-blue-500 px-3 text-lg leading-loose"
80
- aria-invalid = { actionData ?. errors ?. title ? true : undefined }
81
- aria-errormessage = {
82
- actionData ?. errors ?. title ? "title-error" : undefined
83
- }
84
- />
85
- </ label >
86
- { actionData ?. errors ?. title && (
87
- < div className = "pt-1 text-red-700" id = "title-error" >
88
- { actionData . errors . title }
89
- </ div >
90
- ) }
91
- </ div >
92
-
93
- < div >
94
- < label className = "flex w-full flex-col gap-1" >
95
- < span > Body: </ span >
96
- < textarea
97
- ref = { bodyRef }
98
- name = "body"
99
- rows = { 8 }
100
- className = "w-full flex-1 rounded-md border-2 border-blue-500 py-2 px-3 text-lg leading-6"
101
- aria-invalid = { actionData ?. errors ?. body ? true : undefined }
102
- aria-errormessage = {
103
- actionData ?. errors ?. body ? "body-error" : undefined
104
- }
105
- />
106
- </ label >
107
- { actionData ?. errors ?. body && (
108
- < div className = "pt-1 text-red-700" id = "body-error" >
109
- { actionData . errors . body }
110
- </ div >
111
- ) }
112
- </ div >
113
-
114
- < div className = "text-right" >
115
- < button
116
- type = "submit"
117
- className = "rounded bg-blue-500 py-2 px-4 text-white hover:bg-blue-600 focus:bg-blue-400"
118
- >
119
- Save
120
- </ button >
121
- </ div >
122
- </ Form >
123
- ) ;
124
- }
125
-
126
-
127
-
128
-
129
-
130
- export default function IndexRoute ( ) {
95
+ export default function DistantApiMutationRoute ( ) {
131
96
// TODO: it would be more interesting to demo loading users
132
97
// + updating them
133
98
// const { data } = useLoaderData<LoaderData>();
134
99
// if (!data) {
135
100
// return "Ooops, something went wrong :(";
136
101
// }
137
102
const data : any = { posts : [ ] }
103
+ const actionData = useActionData ( ) as ActionData ;
104
+ const nameRef = React . useRef < HTMLInputElement > ( null ) ;
105
+
106
+ React . useEffect ( ( ) => {
107
+ if ( actionData ?. errors ?. name ) {
108
+ nameRef . current ?. focus ( ) ;
109
+ }
110
+ } , [ actionData ] ) ;
138
111
139
112
return (
140
113
< main >
141
- < h1 > Blog Posts</ h1 >
142
- < ul >
143
- { data . posts . map ( ( post : any ) => (
144
- < li key = { post . id } >
145
- { post . title } (by { post . author . name } )
146
- < br />
147
- { post . likes } Likes
148
- < Form method = "post" >
149
- { /* `remix-graphql` will automatically transform all posted
114
+ < h1 > Create a SpaceX user</ h1 >
115
+ < Form method = "post" name = "create" >
116
+ { /* `remix-graphql` will automatically transform all posted
150
117
form data into variables of the same name for the GraphQL
151
118
operation */ }
152
- < input hidden name = "id" value = { post . id } />
153
- < button type = "submit" > Like</ button >
154
- </ Form >
155
- </ li >
156
- ) )
157
- < / u l >
119
+ < input ref = { nameRef } name = "name"
120
+ aria-invalid = { actionData ?. errors ?. name ? true : undefined }
121
+ aria-errormessage = {
122
+ actionData ?. errors ?. name ? "name-error" : undefined
123
+ }
124
+ />
125
+ { actionData ?. errors ?. name && (
126
+ < div className = "pt-1 text-red-700" id = "title-error" >
127
+ { actionData . errors . name }
128
+ </ div >
129
+ ) }
130
+ < button type = "submit" > Submite</ button >
131
+ </ Form >
158
132
</ main >
159
133
) ;
160
134
}
0 commit comments