5 package App::LazyShoppingList::API::v1;
6 use App::LazyShoppingList::API;
13 use experimental 'signatures';
15 set charset => 'UTF-8';
16 set serializer => 'JSON';
17 set content_type => 'application/json';
20 # get the URI for the list of shopping lists
22 return { lists => uri_for('/list') };
25 # get the list of shopping lists
27 my $dbh = get_database;
30 my %r = ( lists_version => get_lists_version($dbh), lists => [] );
32 $dbh->resultset('ShoppingList')
34 { order_by => { -asc => 'name' } } )->all
38 { uri => uri_for( "/list/" . $list->id ), name => $list->name };
45 # create shopping list
47 my $req = request_data;
49 my $name = $req->{name};
52 content_type 'text/plain';
53 return "Missing list name";
56 my $dbh = get_database;
58 my $list = $dbh->resultset('ShoppingList')->create({
60 $list->discard_changes;
62 my $lists_ver = increment_lists_version($dbh);
67 uri => uri_for( '/list/' . $list->id ),
68 version => $list->version,
69 lists_version => $lists_ver
73 # get shopping list items
74 get '/list/:list_id' => sub {
75 my $list_id = route_parameters->get('list_id');
76 length($list_id) and $list_id =~ /^\d{1,18}$/ or return invalid_input;
78 my $dbh = get_database;
81 my %r = ( items => [] );
84 $r{lists_version} = get_lists_version($dbh);
86 my $list = $dbh->resultset('ShoppingList')->find($list_id);
91 content_type 'text/plain';
92 return "No list with that ID found";
95 $r{version} = $list->version;
97 my @items = $dbh->resultset('ShoppingListItem')
98 ->search( undef, { order_by => { -asc => 'id' } } )->all;
99 for my $item (@items) {
102 uri_for( sprintf( "/list/%s/%s", $list->id, $item->id ) ),
103 description => $item->description,
104 done => JSON->boolean( $item->done ),
105 version => $item->version,
114 # create shopping list item
115 post '/list/:id' => sub {
116 my $list_id = route_parameters->get('id');
117 length($list_id) and $list_id =~ /^\d{1,18}$/
118 or return invalid_input('bad list ID');
120 my $req = request_data;
122 my $descr = $req->{description};
123 my $done = JSON->boolean( $req->{done} // 0 );
125 my $dbh = get_database;
129 lists_version => get_lists_version($dbh),
132 my $list = $dbh->resultset('ShoppingList')->find($list_id);
137 content_type 'text/plain';
138 return "No such list";
141 my $item = $dbh->resultset('ShoppingListItem')->create(
142 { shopping_list => $list->id,
143 description => $descr,
147 $item->discard_changes;
149 $list->update( { version => $list->version + 1 } );
151 $r{uri} = uri_for( sprintf( "list/%s/%s", $list->id, $item->id ) );
152 $r{version} = $item->version;
153 $r{list_version} = $list->version;
160 # modify shopping list item
161 put '/list/:list_id/:item_id' => sub {
162 my $list_id = route_parameters->get('list_id');
163 length($list_id) and $list_id =~ /^\d{1,18}$/
164 or return invalid_input('bad list ID');
166 my $item_id = route_parameters->get('item_id');
167 length($item_id) and $item_id =~ /^\d{1,18}$/
168 or return invalid_input('bad item ID');
170 my $req = request_data;
172 my $descr = $req->{description};
173 my $done = JSON->boolean( $req->{done} // 0 );
174 my $version = $req->{version};
176 length($version) and $version =~ /^\d{1,18}$/
177 or return invalid_input('bad version');
179 my $dbh = get_database;
183 lists_version => get_lists_version($dbh),
186 my $list = $dbh->resultset('ShoppingList')->find($list_id);
190 content_type 'text/plain';
191 return "No such list";
194 my $item = $dbh->resultset('ShoppingListItem')->find({shopping_list => $list->id, id => $item_id});
198 content_type 'text/plain';
199 return "No such item";
202 # in case no real changes are needed will return the current state
203 if ( defined($descr) and $descr ne ( $item->description // '' )
204 or defined($done) and $done != $item->done )
206 unless ($version == $item->version) {
209 content_type 'text/plain';
211 sprintf( 'Outdated version (current is %d)', $item->version );
215 defined($descr) ? (description => $descr) : (),
216 defined($done) ? (done => $done) : (),
217 version => $version + 1,
220 $list->update( { version => $list->version + 1 } );
223 $r{uri} = uri_for( sprintf( "list/%s/%s", $list->id, $item->id ) );
224 $r{version} = $item->version;
225 $r{list_version} = $list->version;