Skip to content
Open
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
17 changes: 17 additions & 0 deletions src/assets/icons/BannerIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const BannerIcon = () => {
return (
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="7.5" cy="7.5" r="7.5" fill="#2563EB"/>
<circle cx="7.5" cy="7.5" r="7.5" fill="url(#paint0_linear_40013968_29010)" fillOpacity="0.2"/>
<circle cx="7.5" cy="7.5" r="7.25" stroke="#18181B" strokeOpacity="0.24" strokeWidth="0.5"/>
<path d="M10.23 4.25H4.77C4.48281 4.25 4.25 4.48281 4.25 4.77V6.59C4.25 6.87719 4.48281 7.11 4.77 7.11H10.23C10.5172 7.11 10.75 6.87719 10.75 6.59V4.77C10.75 4.48281 10.5172 4.25 10.23 4.25Z" fill="white"/>
<path d="M4.25 8.93H10.75M4.25 10.75H10.75M4.77 4.25H10.23C10.5172 4.25 10.75 4.48281 10.75 4.77V6.59C10.75 6.87719 10.5172 7.11 10.23 7.11H4.77C4.48281 7.11 4.25 6.87719 4.25 6.59V4.77C4.25 4.48281 4.48281 4.25 4.77 4.25Z" stroke="white" strokeWidth="0.8" strokeLinecap="round" strokeLinejoin="round"/>
<defs>
<linearGradient id="paint0_linear_40013968_29010" x1="7.5" y1="0" x2="7.5" y2="15" gradientUnits="userSpaceOnUse">
<stop stopColor="white"/>
<stop offset="1" stopColor="white" stopOpacity="0"/>
</linearGradient>
</defs>
</svg>
)
}
4 changes: 2 additions & 2 deletions src/assets/icons/MercurConnect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ export const MercurConnect = () => {
width="24"
height="24"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"
colorInterpolationFilters="sRGB"
>
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
Expand Down
9 changes: 9 additions & 0 deletions src/assets/icons/ThumbnailIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const ThumbnailIcon = () => {
return (
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.389 10.3887L1.64055 10.6385C1.35255 10.7345 1.05566 10.5203 1.05566 10.2172V4.78338C1.05566 4.48027 1.35255 4.26604 1.64055 4.36204L2.389 4.61182" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M5.94466 12.0553L5.22644 12.3549C4.93399 12.4767 4.61133 12.2615 4.61133 11.9442V3.05532C4.61133 2.73799 4.93399 2.52288 5.22644 2.64466L5.94466 2.94421" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M8.79762 1.12399L13.4287 3.26088C13.7434 3.40577 13.9452 3.72132 13.9452 4.06799V10.9302C13.9452 11.2769 13.7434 11.5924 13.4287 11.7373L8.79762 13.8742C8.50339 14.0102 8.1665 13.7951 8.1665 13.4707V1.52754C8.1665 1.2031 8.5025 0.987988 8.79762 1.12399Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
)
}
4 changes: 4 additions & 0 deletions src/components/common/file-upload/file-upload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface FileType {
}

export interface FileUploadProps {
disabled?: boolean
label: string
multiple?: boolean
hint?: string
Expand All @@ -18,6 +19,7 @@ export interface FileUploadProps {
}

export const FileUpload = ({
disabled = false,
label,
hint,
multiple = true,
Expand Down Expand Up @@ -95,6 +97,7 @@ export const FileUpload = ({
return (
<div>
<button
disabled={disabled}
ref={dropZoneRef}
type="button"
onClick={handleOpenFileSelector}
Expand Down Expand Up @@ -127,6 +130,7 @@ export const FileUpload = ({
)}
</button>
<input
disabled={disabled}
hidden
ref={inputRef}
onChange={handleFileChange}
Expand Down
5 changes: 5 additions & 0 deletions src/dashboard-app/routes/get-route.map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,11 @@ export function getRouteMap({
};
},
children: [
{
path: "media",
lazy: () =>
import("../../routes/collections/collection-media"),
},
{
path: "edit",
lazy: () =>
Expand Down
187 changes: 127 additions & 60 deletions src/hooks/api/collections.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,112 @@
import { FetchError } from "@medusajs/js-sdk"
import { FindParams, HttpTypes, PaginatedResponse } from "@medusajs/types"
import { FetchError } from '@medusajs/js-sdk';
import { FindParams, HttpTypes, PaginatedResponse } from '@medusajs/types';
import {
QueryKey,
UseMutationOptions,
UseQueryOptions,
useMutation,
useQuery,
} from "@tanstack/react-query"
import { sdk } from "../../lib/client"
import { queryClient } from "../../lib/query-client"
import { queryKeysFactory } from "../../lib/query-key-factory"
import { productsQueryKeys } from "./products"
useQuery
} from '@tanstack/react-query';
import { sdk } from '../../lib/client';
import { queryClient } from '../../lib/query-client';
import { queryKeysFactory } from '../../lib/query-key-factory';
import { productsQueryKeys } from './products';

const COLLECTION_QUERY_KEY = "collections" as const
export const collectionsQueryKeys = queryKeysFactory(COLLECTION_QUERY_KEY)
const COLLECTION_QUERY_KEY = 'collections' as const;
export const collectionsQueryKeys = queryKeysFactory(COLLECTION_QUERY_KEY);

type AdminCollectionDetailMedia = {
id: string;
url: string;
alt_text: string | null;
};

type AdminCollectionDetail = {
id: string;
media: AdminCollectionDetailMedia[];
thumbnail_id: string | null;
icon_id: string | null;
banner_id: string | null;
rank: number;
};

type AdminCollectionWithDetail = HttpTypes.AdminCollection & {
collection_detail?: AdminCollectionDetail;
};

const retrieveCollectionWithDetails = async (id: string) => {
const { collection } = await sdk.admin.productCollection.retrieve(id);

try {
const { collection_detail } = await sdk.client.fetch<{
collection_detail: AdminCollectionDetail;
}>(`/admin/collections/${id}/details`, {
method: 'GET',
});

return {
collection: {
...collection,
collection_detail
} as AdminCollectionWithDetail
};
} catch (error) {
// A collection may not have details yet.
if (error instanceof FetchError && error.status === 404) {
return { collection: collection as AdminCollectionWithDetail };
}

throw error;
}
};

export const usePostCollectionDetails = () => {
return useMutation({
mutationFn: ({
id,
payload
}: {
id: string;
payload: {
media: { delete?: string[]; create?: { url: string; alt_text?: string }[] };
thumbnail?: { url: string} | string | null;
icon?: { url: string} | string |null;
banner?: { url: string} | string| null;
rank?: number | null;
};
}) =>
sdk.client.fetch<{
collection_detail: AdminCollectionDetail;
}>(`/admin/collections/${id}/details`, {
method: 'POST',
body: payload
}),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({ queryKey: collectionsQueryKeys.detail(variables.id) });
}
});
};

export const useCollection = (
id: string,
options?: Omit<
UseQueryOptions<
{ collection: HttpTypes.AdminCollection },
{ collection: AdminCollectionWithDetail },
FetchError,
{ collection: HttpTypes.AdminCollection },
{ collection: AdminCollectionWithDetail },
QueryKey
>,
"queryFn" | "queryKey"
'queryFn' | 'queryKey'
>
) => {
const { data, ...rest } = useQuery({
queryKey: collectionsQueryKeys.detail(id),
queryFn: async () => sdk.admin.productCollection.retrieve(id),
...options,
})
queryFn: async () => retrieveCollectionWithDetails(id),
...options
});

return { ...data, ...rest }
}
return { ...data, ...rest };
};

export const useCollections = (
query?: FindParams & HttpTypes.AdminCollectionListParams,
Expand All @@ -45,17 +117,17 @@ export const useCollections = (
PaginatedResponse<{ collections: HttpTypes.AdminCollection[] }>,
QueryKey
>,
"queryFn" | "queryKey"
'queryFn' | 'queryKey'
>
) => {
const { data, ...rest } = useQuery({
queryKey: collectionsQueryKeys.list(query),
queryFn: async () => sdk.admin.productCollection.list(query),
...options,
})
...options
});

return { ...data, ...rest }
}
return { ...data, ...rest };
};

export const useUpdateCollection = (
id: string,
Expand All @@ -66,18 +138,18 @@ export const useUpdateCollection = (
>
) => {
return useMutation({
mutationFn: (payload) => sdk.admin.productCollection.update(id, payload),
mutationFn: payload => sdk.admin.productCollection.update(id, payload),
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries({ queryKey: collectionsQueryKeys.lists() })
queryClient.invalidateQueries({ queryKey: collectionsQueryKeys.lists() });
queryClient.invalidateQueries({
queryKey: collectionsQueryKeys.detail(id),
})
queryKey: collectionsQueryKeys.detail(id)
});

options?.onSuccess?.(data, variables, context)
options?.onSuccess?.(data, variables, context);
},
...options,
})
}
...options
});
};

export const useUpdateCollectionProducts = (
id: string,
Expand All @@ -88,25 +160,24 @@ export const useUpdateCollectionProducts = (
>
) => {
return useMutation({
mutationFn: (payload) =>
sdk.admin.productCollection.updateProducts(id, payload),
mutationFn: payload => sdk.admin.productCollection.updateProducts(id, payload),
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries({ queryKey: collectionsQueryKeys.lists() })
queryClient.invalidateQueries({ queryKey: collectionsQueryKeys.lists() });
queryClient.invalidateQueries({
queryKey: collectionsQueryKeys.detail(id),
})
queryKey: collectionsQueryKeys.detail(id)
});
/**
* Invalidate products list query to ensure that the products collections are updated.
*/
queryClient.invalidateQueries({
queryKey: productsQueryKeys.lists(),
})
queryKey: productsQueryKeys.lists()
});

options?.onSuccess?.(data, variables, context)
options?.onSuccess?.(data, variables, context);
},
...options,
})
}
...options
});
};

export const useCreateCollection = (
options?: UseMutationOptions<
Expand All @@ -116,34 +187,30 @@ export const useCreateCollection = (
>
) => {
return useMutation({
mutationFn: (payload) => sdk.admin.productCollection.create(payload),
mutationFn: payload => sdk.admin.productCollection.create(payload),
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries({ queryKey: collectionsQueryKeys.lists() })
queryClient.invalidateQueries({ queryKey: collectionsQueryKeys.lists() });

options?.onSuccess?.(data, variables, context)
options?.onSuccess?.(data, variables, context);
},
...options,
})
}
...options
});
};

export const useDeleteCollection = (
id: string,
options?: UseMutationOptions<
HttpTypes.AdminCollectionDeleteResponse,
FetchError,
void
>
options?: UseMutationOptions<HttpTypes.AdminCollectionDeleteResponse, FetchError, void>
) => {
return useMutation({
mutationFn: () => sdk.admin.productCollection.delete(id),
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries({ queryKey: collectionsQueryKeys.lists() })
queryClient.invalidateQueries({ queryKey: collectionsQueryKeys.lists() });
queryClient.invalidateQueries({
queryKey: collectionsQueryKeys.detail(id),
})
queryKey: collectionsQueryKeys.detail(id)
});

options?.onSuccess?.(data, variables, context)
options?.onSuccess?.(data, variables, context);
},
...options,
})
}
...options
});
};
13 changes: 12 additions & 1 deletion src/hooks/table/columns/use-collection-table-columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createColumnHelper } from "@tanstack/react-table"
import { useMemo } from "react"
import { useTranslation } from "react-i18next"
import { TextCell } from "../../../components/table/table-cells/common/text-cell"
import { Thumbnail } from "@components/common/thumbnail"

const columnHelper = createColumnHelper<HttpTypes.AdminCollection>()

Expand All @@ -13,7 +14,17 @@ export const useCollectionTableColumns = () => {
() => [
columnHelper.accessor("title", {
header: t("fields.title"),
cell: ({ getValue }) => <TextCell text={getValue()} />,
cell: ({ getValue, row }) => {
const thumbnailId = (row.original as HttpTypes.AdminCollection & { collection_detail?: { thumbnail_id: string } }).collection_detail?.thumbnail_id

return (
<div className="flex items-center gap-2">
<div className="w-6 h-6">
<Thumbnail src={thumbnailId} />
</div>
<TextCell text={getValue()} />
</div>
)},
}),
columnHelper.accessor("handle", {
header: t("fields.handle"),
Expand Down
Loading