Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Market spec update #104

Merged
merged 20 commits into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
293 changes: 239 additions & 54 deletions components/cart-invoice-card.tsx

Large diffs are not rendered by default.

40 changes: 23 additions & 17 deletions components/display-products.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,28 @@ const DisplayProducts = ({
const productSatisfiesSearchFilter = (productData: ProductData) => {
if (!selectedSearch) return true; // nothing in search bar
if (!productData.title) return false; // we don't want to display it if product has no title
const re = new RegExp(selectedSearch, "gi");
const match = productData.title.match(re);
return match && match.length > 0;
if (selectedSearch.includes("naddr")) {
try {
const parsedNaddr = nip19.decode(selectedSearch);
if (parsedNaddr.type === "naddr") {
return (
productData.d === parsedNaddr.data.identifier &&
productData.pubkey === parsedNaddr.data.pubkey
);
}
return false;
} catch (_) {
return false;
}
} else {
try {
const re = new RegExp(selectedSearch, "gi");
const match = productData.title.match(re);
return match && match.length > 0;
} catch (_) {
return false;
}
}
};

const productSatisfiesAllFilters = (productData: ProductData) => {
Expand All @@ -189,20 +208,7 @@ const DisplayProducts = ({
if (focusedPubkey && productData.pubkey !== focusedPubkey) return;
if (!productSatisfiesAllFilters(productData)) return;
if (productData.images.length === 0) return;

if (
(productData.pubkey ===
"95a5e73109d4c419456372ce99bbf5823dfb6f77aed58d03f77ea052f150ee4a" ||
productData.pubkey ===
"773ed8aba7ee59f6f24612533e891450b6197b5ca24e7680209adb944e330e2f" ||
productData.pubkey ===
"0914be24d8269be22bce80bdc4319bbe7663fd9f84f53288ee9cad94a34cda43" ||
productData.pubkey ===
"996c55eb43d3a29564b5a8cde4bc8c751393daa0d9288772d4213045c6c0fd3e") &&
userPubkey !== productData.pubkey
) {
return; // temp fix, add adult categories or separate from global later
}
if (productData.contentWarning) return;

return (
<ProductCard
Expand Down
15 changes: 10 additions & 5 deletions components/home/marketplace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,14 @@ export function MarketplacePage({
<div className="w-full sm:order-2 sm:w-auto">
<Input
className="text-light-text dark:text-dark-text"
isClearable
placeholder="Search items..."
placeholder="Listing title, naddr1 identifier..."
value={selectedSearch}
startContent={<MagnifyingGlassIcon height={"1em"} />}
onChange={(event) => setSelectedSearch(event.target.value)}
onChange={(event) => {
const value = event.target.value;
setSelectedSearch(value);
}}
onClear={() => setSelectedSearch("")}
/>
</div>

Expand Down Expand Up @@ -352,13 +356,14 @@ export function MarketplacePage({
<Input
className="mt-2 text-light-text dark:text-dark-text"
isClearable
label="Listings"
placeholder="Type to search..."
placeholder="Listing title, naddr1 identifier..."
value={selectedSearch}
startContent={<MagnifyingGlassIcon height={"1em"} />}
onChange={(event) => {
const value = event.target.value;
setSelectedSearch(value);
}}
onClear={() => setSelectedSearch("")}
></Input>
</div>
<div className="flex w-full flex-row gap-2 pb-3">
Expand Down
12 changes: 11 additions & 1 deletion components/messages/chat-message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const ChatMessage = ({
setBuyerPubkey,
setCanReview,
setProductAddress,
setOrderId,
}: {
messageEvent: NostrMessageEvent;
index: number;
Expand All @@ -33,6 +34,7 @@ export const ChatMessage = ({
setBuyerPubkey: (pubkey: string) => void;
setCanReview: (canReview: boolean) => void;
setProductAddress: (productAddress: string) => void;
setOrderId: (orderId: string) => void;
}) => {
const router = useRouter();

Expand Down Expand Up @@ -60,10 +62,18 @@ export const ChatMessage = ({
);
let subject = tagsMap.get("subject") ? tagsMap.get("subject") : null;
let productAddress = tagsMap.get("a") ? tagsMap.get("a") : null;
setCanReview?.(subject === "order-receipt" || subject === "shipping-info");
let orderId = tagsMap.get("order") ? tagsMap.get("order") : null;
setCanReview?.(
subject === "order-info" ||
subject === "order-receipt" ||
subject === "shipping-info",
);
if (productAddress) {
setProductAddress?.(productAddress);
}
if (orderId) {
setOrderId?.(orderId);
}
}, [messageEvent]);

const cashuMatch = messageEvent.content.match(/cashu[A-Za-z]/);
Expand Down
51 changes: 39 additions & 12 deletions components/messages/chat-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { ChatObject, NostrMessageEvent } from "../../utils/types/types";
import { ChatMessage } from "./chat-message";
import { ProfileWithDropdown } from "@/components/utility-components/profile/profile-dropdown";
import {
constructGiftWrappedMessageEvent,
constructGiftWrappedEvent,
constructMessageSeal,
constructMessageGiftWrap,
sendGiftWrappedMessageEvent,
Expand Down Expand Up @@ -77,7 +77,8 @@ export const ChatPanel = ({
["communication", 0],
]),
);
const [productAddress, setProductAddress] = useState<string>("");
const [productAddress, setProductAddress] = useState("");
const [orderId, setOrderId] = useState("");

const reviewsContext = useContext(ReviewsContext);

Expand Down Expand Up @@ -136,25 +137,47 @@ export const ChatPanel = ({
let decodedRandomPubkeyForReceiver = nip19.decode(randomNpubForReceiver);
let decodedRandomPrivkeyForReceiver = nip19.decode(randomNsecForReceiver);

let deliveryTime = data["Delivery Time"];
// Convert delivery days to future unix timestamp
const daysToAdd = parseInt(data["Delivery Time"]);
const currentTimestamp = Math.floor(Date.now() / 1000); // Current unix timestamp in seconds
const futureTimestamp = currentTimestamp + daysToAdd * 24 * 60 * 60; // Add days in seconds

// Create a human-readable date format
const humanReadableDate = new Date(
futureTimestamp * 1000,
).toLocaleDateString("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
});

let shippingCarrier = data["Shipping Carrier"];
let trackingNumber = data["Tracking Number"];
let message =
"Your order from " +
userNPub +
" is expected to arrive within " +
deliveryTime +
" is expected to arrive on " +
humanReadableDate +
". Your " +
shippingCarrier +
" tacking number is: " +
" tracking number is: " +
trackingNumber;
let giftWrappedMessageEvent = await constructGiftWrappedMessageEvent(
let giftWrappedMessageEvent = await constructGiftWrappedEvent(
decodedRandomPubkeyForSender.data as string,
buyerPubkey,
message,
"shipping-info",
undefined,
productAddress,
{
productAddress,
type: 5,
status: "shipped",
isOrder: true,
orderId,
tracking: trackingNumber,
carrier: shippingCarrier,
eta: futureTimestamp, // Using the calculated future timestamp
},
);
let sealedEvent = await constructMessageSeal(
giftWrappedMessageEvent,
Expand Down Expand Up @@ -266,6 +289,7 @@ export const ChatPanel = ({
setBuyerPubkey={setBuyerPubkey}
setCanReview={setCanReview}
setProductAddress={setProductAddress}
setOrderId={setOrderId}
/>
);
})}
Expand Down Expand Up @@ -335,6 +359,7 @@ export const ChatPanel = ({
control={shippingControl}
rules={{
required: "Expected delivery time is required.",
min: 1,
}}
render={({
field: { onChange, onBlur, value },
Expand All @@ -347,12 +372,13 @@ export const ChatPanel = ({
return (
<Input
autoFocus
label="Expected Delivery Time"
placeholder="e.g. 3-5 business days"
label="Expected Delivery Time (days)"
placeholder="e.g. 3"
variant="bordered"
isInvalid={isErrored}
errorMessage={errorMessage}
className="text-light-text dark:text-dark-text"
type="number"
onChange={onChange}
onBlur={onBlur}
value={value}
Expand Down Expand Up @@ -435,7 +461,8 @@ export const ChatPanel = ({
</Modal>
</>
) : (
productAddress !== "" && (
productAddress !== "" &&
buyerPubkey && (
<>
<div className="flex items-center justify-between border-t p-4">
<Button
Expand Down
4 changes: 2 additions & 2 deletions components/messages/messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState, useEffect, useContext } from "react";
import { Filter, nip19, nip44, SimplePool } from "nostr-tools";
import { useRouter } from "next/router";
import {
constructGiftWrappedMessageEvent,
constructGiftWrappedEvent,
constructMessageSeal,
constructMessageGiftWrap,
sendGiftWrappedMessageEvent,
Expand Down Expand Up @@ -255,7 +255,7 @@ const Messages = ({ isPayment }: { isPayment: boolean }) => {
let decodedRandomPrivkeyForSender = nip19.decode(randomNsecForSender);
let decodedRandomPubkeyForReceiver = nip19.decode(randomNpubForReceiver);
let decodedRandomPrivkeyForReceiver = nip19.decode(randomNsecForReceiver);
let giftWrappedMessageEvent = await constructGiftWrappedMessageEvent(
let giftWrappedMessageEvent = await constructGiftWrappedEvent(
userPubkey,
currentChatPubkey,
message,
Expand Down
24 changes: 13 additions & 11 deletions components/product-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -997,17 +997,19 @@ export default function NewForm({
<div className="mx-4 my-2 flex items-center justify-center text-center">
<InformationCircleIcon className="h-6 w-6 text-light-text dark:text-dark-text" />
<p className="ml-2 text-xs text-light-text dark:text-dark-text">
Once sold, you will receive a message containing a{" "}
<Link href="https://cashu.space" passHref legacyBehavior>
<a
target="_blank"
rel="noopener noreferrer"
className="underline"
>
Cashu
</a>
</Link>{" "}
token that you can redeem for Bitcoin.
Your payment preference is set to{" "}
{profileContext.profileData.get(pubkey)?.content
?.payment_preference === "lightning"
? "Lightning"
: "Cashu"}
. You can modify this in your{" "}
<span
className="cursor-pointer underline hover:text-purple-500 dark:hover:text-yellow-500"
onClick={() => router.push("/settings/user-profile")}
>
profile settings
</span>
.
</p>
</div>
</ModalBody>
Expand Down
Loading