Compare commits

...

7 commits

Author SHA1 Message Date
88836082f2 Release the Shopping List button to everyone
Deleting the feature-flag code to gate it, it just now always appears!
Happy launch day!
2024-07-09 13:39:20 -07:00
c55f71a000 Rename GetTheseItemsButton -> ShoppingListButton
Just for consistency with the user-facing branding!
2024-07-09 13:36:42 -07:00
a007479f99 Link to the NC Mall homepage from the Shopping List
We were previously planning a more interesting "Add to Cart"
integration with TNT, but it hasn't panned out! For now, we'll just
link to the NC Mall homepage.
2024-07-09 13:30:28 -07:00
81c6a4a023 Add outfit name to Shopping List page title
Just some extra flair! I had considered something like this before, but
felt it didn't flow well with the old title.
2024-07-09 13:19:23 -07:00
d7eb490ac0 Use a shopping bag icon for the "Shopping List" button
Shopping bag with check! Heck yeah!
2024-07-09 13:14:22 -07:00
c96b726a61 Rebrand the "Item Getting Guide" as "Shopping List"
Two reasons for this new title:
1. The pitch for "Get these items!" is weaker, now that we're not
   getting the power-user integrations we'd planned around.
2. I literally only just thought of it now!
2024-07-09 13:04:22 -07:00
3f47f47ced Prevent analytics script delays from blocking other JS on the page
Oh oops, this is the first script on the page with the `defer`
attribute, which means it needs to run before other scripts with
`defer`—and in this moment, it's not loading for me, which means the
pages aren't working!

I assume Plausible told me to use `defer` rather than `async` because
it expects the page to be ready; okay! Let's just move this to the
very body of the `<head>` instead, so it isn't taking priority over
anything else.
2024-07-07 21:11:14 -07:00
4 changed files with 48 additions and 46 deletions

View file

@ -21,14 +21,26 @@ module ApplicationHelper
end
end
def button_link_to(content, url, icon: nil, **options)
def button_link_to(content_or_url, url = nil, icon: nil, **options)
if url.present?
content = content_or_url
url = url
else
content = nil
url = content_or_url
end
klass = options.fetch(:class, "") + " button"
link_to url, class: klass, **options do
concat icon
concat " "
if block_given?
yield
else
concat content
end
end
end
def advertise_campaign_progress(campaign, &block)
if campaign && campaign.advertised?

View file

@ -34,17 +34,10 @@ import {
QuestionIcon,
WarningTwoIcon,
} from "@chakra-ui/icons";
import { FaCartPlus } from "react-icons/fa6";
import { IoBagCheck } from "react-icons/io5";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import { useSearchParams } from "react-router-dom";
import {
Delay,
ErrorMessage,
Heading1,
Heading2,
useLocalStorage,
} from "../util";
import { Delay, ErrorMessage, Heading1, Heading2 } from "../util";
import Item, { ItemListContainer, ItemListSkeleton } from "./Item";
import { BiRename } from "react-icons/bi";
import { IoCloudUploadOutline } from "react-icons/io5";
@ -279,43 +272,34 @@ function ItemZoneGroupSkeleton({ itemCount }) {
}
/**
* GetTheseItemsButton shows the "Get these items!" button, to link to the
* Item Getting Guide page for the items in this outfit. If there are no items
* being worn, this is disabled.
* ShoppingListButton shows the "Shopping list" button, to link to the Shopping=
* List page for the items in this outfit. If there are no items being worn,
* this is disabled.
*/
function GetTheseItemsButton({ outfitState }) {
const [searchParams] = useSearchParams();
const [isVisible, setIsVisible] = useLocalStorage("DTIShowGetTheseItems");
// Enable this feature by visiting `/outfits/new?features=get-these-items`.
React.useEffect(() => {
const features = searchParams.get("features") ?? "";
if (features.split(",").includes("get-these-items")) {
setIsVisible(true);
}
}, [searchParams, setIsVisible]);
function ShoppingListButton({ outfitState }) {
const itemIds = [...outfitState.wornItemIds].sort();
const targetUrl = `/items/sources/${itemIds.join(",")}`;
const isDisabled = itemIds.length === 0;
if (!isVisible) {
return null;
let targetUrl = `/items/sources/${itemIds.join(",")}`;
if (outfitState.name != null && outfitState.name.trim().length > 0) {
const params = new URLSearchParams();
params.append("for", outfitState.name);
targetUrl += "?" + params.toString();
}
return (
<Tooltip
label="Get these items!"
label="Shopping list"
placement="top"
background="purple.500"
color="white"
>
<IconButton
aria-label="Get these items!"
aria-label="Shopping list"
as={isDisabled ? "button" : "a"}
href={isDisabled ? undefined : targetUrl}
target={isDisabled ? undefined : "_blank"}
icon={<FaCartPlus />}
icon={<IoBagCheck />}
colorScheme="purple"
size="sm"
isRound
@ -460,7 +444,7 @@ function OutfitHeading({ outfitState, outfitSaving, dispatchToOutfit }) {
<Box width="4" flex="1 0 auto" />
<OutfitSavingIndicator outfitSaving={outfitSaving} />
<Box width="3" flex="0 0 auto" />
<GetTheseItemsButton outfitState={outfitState} />
<ShoppingListButton outfitState={outfitState} />
<Box width="2" flex="0 0 auto" />
<Menu placement="bottom-end">
<MenuButton

View file

@ -1,5 +1,11 @@
- title "Item Getting Guide"
%h1#title Item Getting Guide
- page_title = params[:for] ? "Shopping List for \"#{params[:for]}\"" : "Shopping List"
- title page_title
%h1#title= page_title
:markdown
Here's a custom shopping list for exactly the items in your outfit!
Have fun bringing your design to life!!
- if @items[:nc_mall].present?
%h2 NC Mall items
@ -21,16 +27,16 @@
%td.actions-cell
- if @items_needed[:nc_mall].present?
%button{
onclick: "alert('Todo!')",
data: {"action-kind": "bulk-nc-mall"},
}
= button_link_to "https://ncmall.neopets.com/",
target: "_blank",
data: {"action-kind": "bulk-nc-mall"} do
= cart_icon alt: ""
Buy all in NC Mall
%tbody
- @items[:nc_mall].each do |item|
= render "item_list_row", item: do
%button{onclick: "alert('Todo!')"}
= button_link_to "https://ncmall.neopets.com/",
target: "_blank" do
= cart_icon alt: ""
Buy (#{item.current_nc_price} NC)
@ -68,10 +74,9 @@
(~#{dyeworks_estimated_potions_cost_for @items_needed[:dyeworks]} NC)
%td.actions-cell
- if @items_needed[:dyeworks].present?
%button{
onclick: "alert('Todo!')",
data: {"action-kind": "bulk-nc-mall"},
}
= button_link_to "https://ncmall.neopets.com/",
target: "_blank",
data: {"action-kind": "bulk-nc-mall"} do
= cart_icon alt: ""
Buy all in NC Mall
%tbody
@ -106,7 +111,8 @@
}
(Limited-time)
%button{onclick: "alert('Todo!')"}
= button_link_to "https://ncmall.neopets.com/",
target: "_blank" do
= cart_icon alt: ""
Buy base (#{item.dyeworks_base_item.current_nc_price} NC)

View file

@ -13,7 +13,6 @@
%link{href: image_path('favicon.png'), rel: 'icon'}
= yield :stylesheets
= stylesheet_link_tag "application"
= render 'analytics'
= yield :meta
= open_graph_tags
= csrf_meta_tag
@ -24,6 +23,7 @@
= javascript_include_tag 'application', defer: true
= yield :javascripts
= yield :head
= render 'analytics'
%body{:class => body_class}
#container
= yield :before_title