Current section
Files
Jump to
Current section
Files
src/docs@components@product_list.erl
-module(docs@components@product_list).
-compile([no_auto_import, nowarn_unused_vars]).
-export([product_card/2, product_list/2, example_products/0, example_coffee_products/0]).
-export_type([product/0, product_card_props/0, model/0, msg/0, product_list_props/0]).
-type product() :: {product,
integer(),
binary(),
binary(),
binary(),
binary(),
float()}.
-type product_card_props() :: {product_card_props,
product(),
fun((integer()) -> nil)}.
-type model() :: {model, list(integer())}.
-type msg() :: no_op | {hide, integer()} | reset.
-type product_list_props() :: {product_list_props, list(product())}.
-spec product_card(sprocket@context:context(), product_card_props()) -> {sprocket@context:context(),
list(sprocket@element:element())}.
product_card(Ctx, Props) ->
{product_card_props, Product, On_hide} = Props,
sprocket@hooks@state:state(
Ctx,
false,
fun(Ctx@1, In_cart, Set_in_cart) ->
sprocket@hooks@callback:callback(
Ctx@1,
{callback_fn,
fun() ->
Set_in_cart(not In_cart),
nil
end},
{with_deps, [sprocket@hooks:dep(In_cart)]},
fun(Ctx@2, Toggle_in_cart) ->
sprocket@hooks@callback:callback(
Ctx@2,
{callback_fn,
fun() ->
On_hide(erlang:element(2, Product)),
nil
end},
on_mount,
fun(Ctx@3, On_hide@1) ->
{product, _, Name, Description, Img_url, Qty, Price} = Product,
sprocket@component:render(
Ctx@3,
[sprocket@html:'div'(
[sprocket@html@attributes:class(
<<"flex flex-row bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700"/utf8>>
)],
[sprocket@html:'div'(
[sprocket@html@attributes:class(
<<"w-1/3 rounded-l-lg overflow-hidden"/utf8>>
)],
[sprocket@html:img(
[sprocket@html@attributes:class(
<<"object-cover h-52 w-full"/utf8>>
),
sprocket@html@attributes:src(
Img_url
),
sprocket@html@attributes:alt(
<<"product image"/utf8>>
)]
)]
),
sprocket@html:'div'(
[sprocket@html@attributes:class(
<<"flex-1 flex flex-col p-5"/utf8>>
)],
[sprocket@html:'div'(
[sprocket@html@attributes:class(
<<"flex-1 flex flex-row"/utf8>>
)],
[sprocket@html:'div'(
[sprocket@html@attributes:class(
<<"flex-1"/utf8>>
)],
[sprocket@html:h5_text(
[sprocket@html@attributes:class(
<<"text-xl font-semibold tracking-tight text-gray-900 dark:text-white"/utf8>>
)],
Name
),
sprocket@html:div_text(
[sprocket@html@attributes:class(
<<"py-2 text-gray-500"/utf8>>
)],
Description
)]
),
sprocket@html:'div'(
[],
[sprocket@html:'div'(
[sprocket@html@attributes:class(
<<"flex-1 flex flex-col text-right"/utf8>>
)],
[sprocket@html:div_text(
[sprocket@html@attributes:class(
<<"text-xl font-bold text-gray-900 dark:text-white"/utf8>>
)],
<<"$"/utf8,
(gleam@float:to_string(
Price
))/binary>>
),
sprocket@html:div_text(
[sprocket@html@attributes:class(
<<"text-sm text-gray-500"/utf8>>
)],
Qty
)]
)]
)]
),
sprocket@html:'div'(
[sprocket@html@attributes:class(
<<"flex flex flex-row justify-end"/utf8>>
)],
[sprocket@html:button_text(
[sprocket@html@attributes:class(
<<"text-blue-700 hover:text-blue-800 hover:underline focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:text-blue-600 dark:hover:text-blue-700 dark:focus:ring-blue-800 mr-2"/utf8>>
),
sprocket@html@attributes:on_click(
On_hide@1
)],
<<"Not Interested"/utf8>>
) |
case In_cart of
true ->
[sprocket@html:button(
[sprocket@html@attributes:class(
<<"text-white bg-green-700 hover:bg-green-800 focus:ring-4 focus:outline-none focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800"/utf8>>
),
sprocket@html@attributes:on_click(
Toggle_in_cart
)],
[sprocket@html:i(
[sprocket@html@attributes:class(
<<"fa-solid fa-check mr-2"/utf8>>
)],
[]
),
sprocket@html:text(
<<"Added to Cart!"/utf8>>
)]
)];
false ->
[sprocket@html:button(
[sprocket@html@attributes:class(
<<"text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"/utf8>>
),
sprocket@html@attributes:on_click(
Toggle_in_cart
)],
[sprocket@html:i(
[sprocket@html@attributes:class(
<<"fa-solid fa-cart-shopping mr-2"/utf8>>
)],
[]
),
sprocket@html:text(
<<"Add to Cart"/utf8>>
)]
)]
end]
)]
)]
)]
)
end
)
end
)
end
).
-spec update(model(), msg()) -> model().
update(Model, Msg) ->
case Msg of
no_op ->
Model;
{hide, Id} ->
{model, [Id | erlang:element(2, Model)]};
reset ->
{model, []}
end.
-spec initial() -> model().
initial() ->
{model, []}.
-spec product_list(sprocket@context:context(), product_list_props()) -> {sprocket@context:context(),
list(sprocket@element:element())}.
product_list(Ctx, Props) ->
{product_list_props, Products} = Props,
sprocket@hooks@reducer:reducer(
Ctx,
initial(),
fun update/2,
fun(Ctx@1, _use1) ->
{state, {model, Hidden}, Dispatch} = _use1,
sprocket@hooks@callback:callback(
Ctx@1,
{callback_fn, fun() -> Dispatch(reset) end},
on_mount,
fun(Ctx@2, Reset) ->
sprocket@component:render(
Ctx@2,
[sprocket@html:'div'(
[],
[sprocket@html:ul(
[sprocket@html@attributes:role(
<<"list"/utf8>>
),
sprocket@html@attributes:class(
<<"flex flex-col"/utf8>>
)],
begin
_pipe = Products,
gleam@list:filter_map(
_pipe,
fun(Product) ->
case gleam@list:contains(
Hidden,
erlang:element(
2,
Product
)
) of
true ->
{error, nil};
false ->
{ok,
sprocket@html:keyed(
gleam@int:to_string(
erlang:element(
2,
Product
)
),
sprocket@html:li(
[sprocket@html@attributes:class(
<<"py-3 mr-4"/utf8>>
)],
[sprocket@component:component(
fun product_card/2,
{product_card_props,
Product,
fun(
_
) ->
Dispatch(
{hide,
erlang:element(
2,
Product
)}
)
end}
)]
)
)}
end
end
)
end
) |
case gleam@list:is_empty(Hidden) of
true ->
[];
false ->
[sprocket@html:button(
[sprocket@html@attributes:class(
<<"mt-5 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"/utf8>>
),
sprocket@html@attributes:on_click(
Reset
)],
[sprocket@html:text(
<<"Show Hidden ("/utf8>>
),
sprocket@html:text(
gleam@int:to_string(
gleam@list:length(
Hidden
)
)
),
sprocket@html:text(
<<")"/utf8>>
)]
)]
end]
)]
)
end
)
end
).
-spec example_products() -> list(product()).
example_products() ->
[{product,
2255,
<<"Eco-Friendly Bamboo Cutting Board"/utf8>>,
<<"This sustainable bamboo cutting board is perfect for slicing and dicing vegetables, fruits, and meats. The natural antibacterial properties of bamboo ensure a hygienic cooking experience."/utf8>>,
<<"https://images.pexels.com/photos/6489734/pexels-photo-6489734.jpeg"/utf8>>,
<<"12 x 8 inches"/utf8>>,
24.99},
{product,
2256,
<<"Wireless Bluetooth Earbuds"/utf8>>,
<<"Enjoy true wireless freedom with these Bluetooth earbuds. The ergonomic design provides a comfortable fit, and the advanced Bluetooth 5.0 technology ensures a stable connection with your devices. With noise-cancellation and high-quality sound, these earbuds are perfect for music lovers and hands-free calls. Comes with a portable charging case for extended use."/utf8>>,
<<"https://images.pexels.com/photos/8380433/pexels-photo-8380433.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"/utf8>>,
<<"1 set"/utf8>>,
49.99},
{product,
2257,
<<"Vintage Leather Messenger Bag"/utf8>>,
<<"This classic leather messenger bag is a perfect blend of style and functionality. Handcrafted from genuine leather, it offers ample space for your laptop, documents, and other essentials. The adjustable shoulder strap provides comfort during travel, while the vintage design adds a touch of sophistication to your look."/utf8>>,
<<"https://images.pexels.com/photos/1152077/pexels-photo-1152077.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"/utf8>>,
<<"1 bag"/utf8>>,
89.99},
{product,
2258,
<<"Fitness Tracker Smart Watch"/utf8>>,
<<"Stay on top of your fitness goals with this feature-packed smartwatch. It tracks your steps, heart rate, sleep patterns, and various exercises. The color touchscreen display provides easy navigation through your notifications, calls, and messages. It's water-resistant and comes with a long-lasting battery for continuous use."/utf8>>,
<<"https://images.pexels.com/photos/437036/pexels-photo-437036.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"/utf8>>,
<<"1 watch"/utf8>>,
69.99},
{product,
2259,
<<"Organic Aromatherapy Candle"/utf8>>,
<<"Create a fresh ambiance with this organic aromatherapy candle. Hand-poured with pure essential oils, the fresh scent of citrus will brighten up your room. The natural soy wax ensures a clean and long-lasting burn, while the elegant glass jar adds a touch of luxury to any room."/utf8>>,
<<"https://images.pexels.com/photos/7260249/pexels-photo-7260249.jpeg"/utf8>>,
<<"1 candle"/utf8>>,
19.99}].
-spec example_coffee_products() -> list(product()).
example_coffee_products() ->
[{product,
2255,
<<"Morning Bliss"/utf8>>,
<<"A medium-bodied coffee with a balanced acidity that pairs perfectly with breakfast."/utf8>>,
<<"https://images.pexels.com/photos/17032151/pexels-photo-17032151/free-photo-of-a-cup-of-espresso-on-a-table-by-the-window.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"/utf8>>,
<<"12 oz bag"/utf8>>,
12.99},
{product,
2256,
<<"Sunset Serenade"/utf8>>,
<<"A mix of Ethiopian and Kenyan beans, carefully selected for their bright berry undertones and floral aroma and roasted at a medium-dark level."/utf8>>,
<<"https://images.pexels.com/photos/9716818/pexels-photo-9716818.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"/utf8>>,
<<"10 oz bag"/utf8>>,
14.99},
{product,
2257,
<<"Island Breeze"/utf8>>,
<<"A unique fusion of Indonesian Sumatra and Hawaiian Kona beans that are dark-roasted"/utf8>>,
<<"https://images.pexels.com/photos/2252307/pexels-photo-2252307.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"/utf8>>,
<<"8 oz bag"/utf8>>,
17.99},
{product,
2258,
<<"Zen Garden Blend"/utf8>>,
<<"A mindful combination of shade-grown Colombian and Costa Rican beans, carefully roasted to a medium-light profile."/utf8>>,
<<"https://images.pexels.com/photos/539694/pexels-photo-539694.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"/utf8>>,
<<"16 oz bag"/utf8>>,
15.99},
{product,
2259,
<<"Mocha Madness"/utf8>>,
<<"A decadent blend of Central American beans blended with premium cocoa nibs that are medium-roasted."/utf8>>,
<<"https://images.pexels.com/photos/2396220/pexels-photo-2396220.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"/utf8>>,
<<"12 oz bag"/utf8>>,
19.99}].