Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
s8_ivanov_r
VPL-pizza-shop-blazor
Commits
3c925a16
Commit
3c925a16
authored
Jan 25, 2019
by
Ryan Nowak
Browse files
Add part two
parent
3ec0a5f3
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
210 additions
and
8 deletions
+210
-8
README.md
README.md
+16
-7
save-points/02-customize-a-pizza/BlazingPizza.Client/Pages/Index.cshtml
...-customize-a-pizza/BlazingPizza.Client/Pages/Index.cshtml
+80
-1
save-points/02-customize-a-pizza/BlazingPizza.Client/Shared/ConfigurePizzaDialog.cshtml
...za/BlazingPizza.Client/Shared/ConfigurePizzaDialog.cshtml
+96
-0
save-points/02-customize-a-pizza/BlazingPizza.Client/Shared/ConfiguredPizzaItem.cshtml
...zza/BlazingPizza.Client/Shared/ConfiguredPizzaItem.cshtml
+18
-0
No files found.
README.md
View file @
3c925a16
...
...
@@ -17,21 +17,30 @@ Sessions
-
Fetch specials list from backend
-
Display list of pizza names
-
Pizza card component (no templates yet)
-
Parameters: Pizza object
-
Parameters: Pizza
Special
object
Lunch
1.
Handling UI events & data binding
-
Clickable pizza cards
-
Cover
`@page`
-
Pizza customization
-
Price updated based on selections
-
Place order button, sends order to the backend
-
Confirmation screen
-
Make special pizza cards clickable
-
Clicking on a special brings up the new customize dialog
-
Index needs to handle the hide/show of the dialog
-
Index needs to pass in the Pizza object as well as two 'command' delegates
-
Using
`bind`
and
`onclick`
on the customize dialog to update prices in real time
-
explain the difference between
`bind`
and
`bind-value-oninput`
on the slider
-
cancel button should close the dialog
-
confirm button should close the dialog and add to order
-
now add the markup for sidebar which will display orders
-
add a ConfiguredPizzaItem component
-
hook up the order button to do an HTTP POST and clear the order
-
(no way to see existing orders yet)
1.
DI
-
Create a service for interacting with the backend, repository abstraction
-
Refactor HttpClient code to use service instead
-
Talk to DI scopes
1.
Build the order status screen
-
Confirmation screen
-
Cover
`@page`
1.
JS interop
-
Add order status
-
Real status (map location, time to delivery) via polling
...
...
save-points/02-customize-a-pizza/BlazingPizza.Client/Pages/Index.cshtml
View file @
3c925a16
...
...
@@ -7,7 +7,7 @@
{
@foreach (var special in specials)
{
<li
style=
"background-image: url('@special.ImageUrl')"
>
<li
onclick=
"@(() => ShowConfigurePizzaDialog(special))"
style=
"background-image: url('@special.ImageUrl')"
>
<div
class=
"pizza-info"
>
<span
class=
"title"
>
@special.Name
</span>
@special.Description
...
...
@@ -19,11 +19,90 @@
</ul>
</div>
<div
class=
"sidebar"
>
@if (order.Pizzas.Any())
{
<div
class=
"order-contents"
>
<h2>
Your order
</h2>
@foreach (var configuredPizza in order.Pizzas)
{
<ConfiguredPizzaItem
Pizza=
"configuredPizza"
OnRemoved=
"() => RemoveConfiguredPizza(configuredPizza)"
/>
}
</div>
}
else
{
<div
class=
"empty-cart"
>
Choose a pizza
<br>
to get started
</div>
}
<div
class=
"order-total @(order.Pizzas.Any() ? "
"
:
"
hidden
")"
>
Total:
<span
class=
"total-price"
>
@order.GetFormattedTotalPrice()
</span>
<button
class=
"btn btn-warning"
disabled=
"@(order.Pizzas.Count == 0)"
onclick=
"@PlaceOrder"
>
Order >
</button>
</div>
</div>
@if (showingConfigureDialog)
{
<ConfigurePizzaDialog
Pizza=
"configuringPizza"
OnCancel=
"CancelConfigurePizzaDialog"
OnConfirm=
"ConfirmConfigurePizzaDialog"
/>
}
@functions {
List
<PizzaSpecial>
specials;
Pizza configuringPizza;
bool showingConfigureDialog;
Order order = new Order();
protected async override Task OnInitAsync()
{
specials = await HttpClient.GetJsonAsync
<List
<
PizzaSpecial
>
>("/specials");
}
void ShowConfigurePizzaDialog(PizzaSpecial special)
{
configuringPizza = new Pizza()
{
Special = special,
SpecialId = special.Id,
Size = Pizza.DefaultSize,
Toppings = new List
<PizzaTopping>
(),
};
showingConfigureDialog = true;
}
void CancelConfigurePizzaDialog()
{
configuringPizza = null;
showingConfigureDialog = false;
StateHasChanged();
}
void ConfirmConfigurePizzaDialog()
{
order.Pizzas.Add(configuringPizza);
configuringPizza = null;
showingConfigureDialog = false;
StateHasChanged();
}
void RemoveConfiguredPizza(Pizza pizza)
{
order.Pizzas.Remove(pizza);
StateHasChanged();
}
async Task PlaceOrder()
{
await HttpClient.PostJsonAsync("/orders", order);
order = new Order();
}
}
save-points/02-customize-a-pizza/BlazingPizza.Client/Shared/ConfigurePizzaDialog.cshtml
0 → 100644
View file @
3c925a16
@inject HttpClient HttpClient
<div
class=
"dialog-container"
>
<div
class=
"dialog"
>
<div
class=
"dialog-title"
>
<h2>
@Pizza.Special.Name
</h2>
@Pizza.Special.Description
</div>
<form
class=
"dialog-body"
>
<div>
<label>
Size:
</label>
<input
type=
"range"
min=
"@Pizza.MinimumSize"
max=
"@Pizza.MaximumSize"
step=
"1"
bind-value-oninput=
"Pizza.Size"
/>
<span
class=
"size-label"
>
@(Pizza.Size)" (£@(Pizza.GetFormattedTotalPrice()))
</span>
</div>
<div>
<label>
Extra Toppings:
</label>
@if (toppings == null)
{
<select
class=
"custom-select"
disabled
>
<option>
(loading...)
</option>
</select>
}
else if (Pizza.Toppings.Count >= 6)
{
<div>
(maximum reached)
</div>
}
else
{
<select
class=
"custom-select"
onchange=
"@ToppingSelected"
>
<option
value=
"-1"
disabled
selected
>
(select)
</option>
@for (var i = 0; i
<
toppings.Count
;
i
++)
{
<
option
value=
"@i"
>
@toppings[i].Name - (£@(toppings[i].GetFormattedPrice()))
</option>
}
</select>
}
</div>
<div
class=
"toppings"
>
@foreach (var topping in Pizza.Toppings)
{
<div
class=
"topping"
>
@topping.Topping.Name
<span
class=
"topping-price"
>
@topping.Topping.GetFormattedPrice()
</span>
<button
type=
"button"
class=
"delete-topping"
onclick=
"@(() => RemoveTopping(topping.Topping))"
>
x
</button>
</div>
}
</div>
</form>
<div
class=
"dialog-buttons"
>
<button
class=
"btn btn-secondary mr-auto"
onclick=
"@OnCancel"
>
Cancel
</button>
<span
class=
"mr-center"
>
Price:
<span
class=
"price"
>
@(Pizza.GetFormattedTotalPrice())
</span>
</span>
<button
class=
"btn btn-success ml-auto"
onclick=
"@OnConfirm"
>
Order >
</button>
</div>
</div>
</div>
@functions {
List
<Topping>
toppings { get; set; }
[Parameter] Pizza Pizza { get; set; }
[Parameter] Action OnCancel { get; set; }
[Parameter] Action OnConfirm { get; set; }
protected async override Task OnInitAsync()
{
toppings = await HttpClient.GetJsonAsync
<List
<
Topping
>
>("/toppings");
}
void ToppingSelected(UIChangeEventArgs e)
{
if (int.TryParse((string)e.Value, out var index)
&&
index >= 0)
{
AddTopping(toppings[index]);
}
}
void AddTopping(Topping topping)
{
if (Pizza.Toppings.Find(pt => pt.Topping == topping) == null)
{
Pizza.Toppings.Add(new PizzaTopping() { Topping = topping });
}
}
void RemoveTopping(Topping topping)
{
Pizza.Toppings.RemoveAll(pt => pt.Topping == topping);
StateHasChanged();
}
}
save-points/02-customize-a-pizza/BlazingPizza.Client/Shared/ConfiguredPizzaItem.cshtml
0 → 100644
View file @
3c925a16
<div
class=
"cart-item"
>
<a
onclick=
@OnRemoved
class=
"delete-item"
>
x
</a>
<div
class=
"title"
>
@(Pizza.Size)" @Pizza.Special.Name
</div>
<ul>
@foreach (var topping in Pizza.Toppings)
{
<li>
+ @topping.Topping.Name
</li>
}
</ul>
<div
class=
"item-price"
>
@Pizza.GetFormattedTotalPrice()
</div>
</div>
@functions {
[Parameter] Pizza Pizza { get; set; }
[Parameter] Action OnRemoved { get; set; }
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment