diff --git a/apps/platform/src/features/resources/components/resourcesList.tsx b/apps/platform/src/features/resources/components/resourcesList.tsx
index 74e9f1b..9bbbe28 100644
--- a/apps/platform/src/features/resources/components/resourcesList.tsx
+++ b/apps/platform/src/features/resources/components/resourcesList.tsx
@@ -1,15 +1,84 @@
+import { LockIcon } from "@hugeicons/core-free-icons";
+import { HugeiconsIcon } from "@hugeicons/react";
+import { Button, Input } from "@opencircle/ui";
+import { useState } from "react";
+import { useAccount } from "../../../features/auth/hooks/useAccount";
+import { api } from "../../../utils/api";
import { useResources } from "../hooks/useResources";
import { ResourceCard } from "./resourceCard";
+import { ResourcesListSkeleton } from "./resourcesListSkeleton";
interface ResourcesListProps {
channelId?: string;
}
export const ResourcesList = ({ channelId }: ResourcesListProps) => {
- const { resources, isResourcesLoading } = useResources(channelId);
+ const { resources, isResourcesLoading, error } = useResources(channelId);
+ const [inviteCode, setInviteCode] = useState("");
+ const [isSubmitting, setIsSubmitting] = useState(false);
+ const { account } = useAccount();
+
+ const handleRequestAccess = async () => {
+ if (!inviteCode.trim()) return;
+
+ setIsSubmitting(true);
+ try {
+ if (!account?.id) {
+ alert("Please log in to request access");
+ return;
+ }
+
+ const response = await api.inviteCodes.validate({
+ code: inviteCode,
+ user_id: account.id,
+ });
+
+ if (response.valid) {
+ // Successfully validated - refresh resources to show content
+ window.location.reload();
+ } else {
+ alert(response.message || "Failed to validate invite code");
+ }
+ } catch (err) {
+ console.error("Error validating invite code:", err);
+ alert("An error occurred while validating the invite code");
+ } finally {
+ setIsSubmitting(false);
+ }
+ };
if (isResourcesLoading) {
- return
Loading resources...
;
+ return ;
+ }
+
+ if (error) {
+ return (
+
+
+
+
+
+ You are not eligible to access this content.
+
+ {account?.id && (
+
+ setInviteCode(e.target.value)}
+ />
+
+
+ )}
+
+ );
}
if (!resources || resources.length === 0) {
diff --git a/apps/platform/src/features/resources/components/resourcesListSkeleton.tsx b/apps/platform/src/features/resources/components/resourcesListSkeleton.tsx
new file mode 100644
index 0000000..2c54702
--- /dev/null
+++ b/apps/platform/src/features/resources/components/resourcesListSkeleton.tsx
@@ -0,0 +1,32 @@
+export const ResourcesListSkeleton = () => {
+ return (
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+
+
+ {/* URL link skeleton */}
+
+
+ {/* Description skeleton - only show if there might be one */}
+
+
+ {/* Footer info skeleton */}
+
+
+
+
+ ))}
+
+ );
+};
diff --git a/apps/platform/src/features/resources/hooks/useResources.ts b/apps/platform/src/features/resources/hooks/useResources.ts
index b8b1546..a0602c0 100644
--- a/apps/platform/src/features/resources/hooks/useResources.ts
+++ b/apps/platform/src/features/resources/hooks/useResources.ts
@@ -1,8 +1,9 @@
import { useQuery } from "@tanstack/react-query";
+import { HTTPError } from "ky";
import { api } from "../../../utils/api";
export const useResources = (channelId?: string) => {
- const { data, isLoading } = useQuery({
+ const { data, isLoading, error } = useQuery({
queryKey: ["resources", { channelId }],
queryFn: async () => {
if (channelId) {
@@ -10,10 +11,18 @@ export const useResources = (channelId?: string) => {
}
return await api.resources.getAll();
},
+ retry: (failureCount, error) => {
+ if (error instanceof HTTPError && error.response.status === 403) {
+ console.error("Not Eligible to access");
+ return false;
+ }
+ return failureCount < 3;
+ },
});
return {
resources: data,
isResourcesLoading: isLoading,
+ error,
};
};