Skip to content

Commit

Permalink
recommendation setup
Browse files Browse the repository at this point in the history
  • Loading branch information
Charlie ⚡ committed Sep 5, 2022
1 parent c97b8e0 commit af3f9d4
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 43 deletions.
7 changes: 5 additions & 2 deletions components/add-feed.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useFormik } from "formik";
import { useState } from "react";
import { useCallback, useState } from "react";
import { addFeed } from "../lib/fetcher";
import { SuperButton, Button } from "./ui/button";
import { Label, Fieldset, Input } from "./ui/input";
Expand Down Expand Up @@ -36,14 +36,17 @@ export const AddFeedForm = (props: AddFeedFormProps) => {

export const AddFeed = () => {
const [isOpen, setOpen] = useState(false);
const handleSubmit = useCallback((url: string) => {
addFeed(url);
}, []);
return (
<>
<Button onClick={() => setOpen(true)}>Add Feed</Button>
<Dialog isOpen={isOpen} onClose={() => setOpen(false)} title="Add Feed">
<div className="mt-2 mb-8 text-sm opacity-50">
Make changes to your profile here. Click save when you&apos;re done.
</div>
<AddFeedForm onSubmit={addFeed} />
<AddFeedForm onSubmit={handleSubmit} />
</Dialog>
</>
);
Expand Down
54 changes: 54 additions & 0 deletions components/recommendation-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { useCallback } from "react";
import useSWR from "swr";
import { addFeed, getFeeds } from "../lib/fetcher";
import { RecommendationCard } from "./ui/recommendation-card";

interface RecommendationListProps {
recommended: [string, Array<{ displayName: string; link: string }>][];
}

export const RecommendationList = ({ recommended }: RecommendationListProps) => {
const { data, error, mutate } = useSWR("recommended feeds", getFeeds);

const handleClick = useCallback(
async (link: string) => {
const data = await addFeed(link);

await mutate((prevData) => {
prevData?.feeds.push(data.addFeed);

return prevData;
});
},
[mutate]
);

return (
<div className="space-y-8 pb-8">
{error && <div>{error.toString()}</div>}
{recommended.map(([key, recommendedFeeds], idx) => {
return (
<section key={idx}>
<h2 className="text-lg opacity-50">{key}</h2>

<ul
role="list"
className="mt-4 grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
{recommendedFeeds.map((r) => (
<li key={r.displayName} className="col-span-1">
<RecommendationCard
displayName={r.displayName}
link={r.link}
feeds={data}
error={error}
onSubscribe={handleClick}
/>
</li>
))}
</ul>
</section>
);
})}
</div>
);
};
61 changes: 48 additions & 13 deletions components/ui/recommendation-card.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,59 @@
import { useCallback } from "react";
import { useCallback, useMemo } from "react";
import { FiRss } from "react-icons/fi";
import { addFeed } from "../../lib/fetcher";
import { GetFeedsQuery } from "../../lib/types";
import { LoadingIndicator } from "./activity-indicator";

interface RecommendationCardProps {
displayName: string;
link: string;
type?: "feed" | "twitter";
feeds?: GetFeedsQuery;
error?: any;
onSubscribe(link: string): void;
}

export const RecommendationCard = ({ displayName, link }: RecommendationCardProps) => {
export const RecommendationCard = ({
displayName,
link,
onSubscribe,
feeds,
error,
}: RecommendationCardProps) => {
const handleClick = useCallback(() => {
return addFeed(link);
}, [link]);
return onSubscribe(link);
}, [onSubscribe, link]);

const isLoading = !error && !feeds;

const hasFeed = useMemo(() => {
if (feeds) {
return feeds.feeds.findIndex((f) => f?.feedURL === link) > -1;
}

return false;
}, [feeds, link]);

let content = (
<button
onClick={handleClick}
className="relative -mr-px inline-flex w-0 flex-1 items-center justify-center rounded-bl-lg border border-transparent py-4 text-sm font-medium hover:text-gray-500">
<FiRss className="h-5 w-5 text-zinc-400" aria-hidden="true" />
<span className="ml-3">Subscribe</span>
</button>
);

if (isLoading) {
content = <LoadingIndicator />;
}

if (hasFeed) {
content = (
<div className="relative -mr-px inline-flex w-0 flex-1 items-center justify-center rounded-bl-lg border border-transparent py-4 text-sm font-medium opacity-50 hover:text-gray-500">
<FiRss className="h-5 w-5 text-zinc-400" aria-hidden="true" />
<span className="ml-3">Subscribed</span>
</div>
);
}

return (
<div className="divide-y divide-zinc-500 rounded-lg bg-white dark:bg-zinc-800">
Expand All @@ -25,14 +67,7 @@ export const RecommendationCard = ({ displayName, link }: RecommendationCardProp
</div>
<div>
<div className="-mt-px flex divide-x divide-zinc-500">
<div className="flex w-0 flex-1">
<button
onClick={handleClick}
className="relative -mr-px inline-flex w-0 flex-1 items-center justify-center rounded-bl-lg border border-transparent py-4 text-sm font-medium hover:text-gray-500">
<FiRss className="h-5 w-5 text-zinc-400" aria-hidden="true" />
<span className="ml-3">Subscribe</span>
</button>
</div>
<div className="flex w-0 flex-1">{content}</div>
</div>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions lib/document.graphql
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
fragment FeedDetails on Feed {
id
title
link
feedURL
}

query GetFeeds {
Expand Down
3 changes: 2 additions & 1 deletion lib/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ export const markAsRead = async (entryID: string) => {
};
export const addFeed = async (url: string) => {
try {
await sdk.CreateFeed({
const data = await sdk.CreateFeed({
url,
});
console.log(url);
return data;
} catch (error: any) {
throw new Error(error);
}
Expand Down
21 changes: 18 additions & 3 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export enum EntryFilter {

export type Feed = {
__typename?: "Feed";
feedURL: Scalars["String"];
id: Scalars["ID"];
lastFetched: Scalars["Date"];
link: Scalars["String"];
Expand Down Expand Up @@ -103,13 +104,25 @@ export type QueryFeedArgs = {
id: Scalars["ID"];
};

export type FeedDetailsFragment = { __typename?: "Feed"; id: string; title: string };
export type FeedDetailsFragment = {
__typename?: "Feed";
id: string;
title: string;
link: string;
feedURL: string;
};

export type GetFeedsQueryVariables = Exact<{ [key: string]: never }>;

export type GetFeedsQuery = {
__typename?: "Query";
feeds: Array<{ __typename?: "Feed"; id: string; title: string } | null>;
feeds: Array<{
__typename?: "Feed";
id: string;
title: string;
link: string;
feedURL: string;
} | null>;
};

export type EntryDetailsFragment = {
Expand Down Expand Up @@ -175,7 +188,7 @@ export type CreateFeedMutationVariables = Exact<{

export type CreateFeedMutation = {
__typename?: "Mutation";
addFeed: { __typename?: "Feed"; id: string; title: string };
addFeed: { __typename?: "Feed"; id: string; title: string; link: string; feedURL: string };
};

export type MarkAsReadMutationVariables = Exact<{
Expand Down Expand Up @@ -207,6 +220,8 @@ export const FeedDetailsFragmentDoc = gql`
fragment FeedDetails on Feed {
id
title
link
feedURL
}
`;
export const EntryDetailsFragmentDoc = gql`
Expand Down
20 changes: 2 additions & 18 deletions pages/recommendations.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { InferGetStaticPropsType, NextPage } from "next";
import { RecommendedKeyArray } from "../server/recommended";
import { RecommendationCard } from "../components/ui/recommendation-card";
import { RecommendationList } from "../components/recommendation-list";

export const getStaticProps = async () => {
return {
Expand All @@ -15,23 +15,7 @@ const RecommendationsPage: NextPage<InferGetStaticPropsType<typeof getStaticProp
}) => {
return (
<div className="mx-auto max-w-7xl space-y-16 pt-16">
{recommended.map(([key, recommendedFeeds], idx) => {
return (
<section key={idx}>
<h2 className="text-lg opacity-50">{key}</h2>

<ul
role="list"
className="mt-4 grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
{recommendedFeeds.map((r) => (
<li key={r.displayName} className="col-span-1">
<RecommendationCard displayName={r.displayName} link={r.link} />
</li>
))}
</ul>
</section>
);
})}
<RecommendationList recommended={recommended} />
</div>
);
};
Expand Down
13 changes: 9 additions & 4 deletions server/recommended.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const LIFESTYLE: RecommendedField[] = [

const RELEVANT: RecommendedField[] = [
{
link: "https://charliewil.co/rss.xml",
link: "https://charliewil.co/rss",
displayName: "Charlie's Blog",
},
{
Expand All @@ -63,11 +63,16 @@ const RELEVANT: RecommendedField[] = [
},
];

export const RecommendedKeyArray = [
export const RecommendedKeyArray: [string, RecommendedField[]][] = [
["News", NEWS],
["Tech", TECH],
["Lifestyle", LIFESTYLE],
["Relevant", RELEVANT],
] as const;
];

export const RecommendationMap = new Map(RecommendedKeyArray);
export const RecommendationMap = new Map<string, RecommendedField[]>([
["News", NEWS],
["Tech", TECH],
["Lifestyle", LIFESTYLE],
["Relevant", RELEVANT],
]);
1 change: 1 addition & 0 deletions server/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const query: QueryResolvers<Context> = {
async feeds(_parent, _args, { prisma }) {
const feeds = await prisma.feed.findMany();

console.log(feeds);
return feeds;
},
async feed(_parent, { id }, { prisma }) {
Expand Down
10 changes: 8 additions & 2 deletions server/structs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import type { Entry } from "@prisma/client";
import type { Entry, Feed } from "@prisma/client";
import type { RSSItem } from "./rss";
import type { Entry as EntryType } from "./types";
import type { Entry as EntryType, Feed as FeedType } from "./types";

export const mapFeedtoAPIFeed = (feed: Feed): FeedType => {
return {
...feed,
};
};

export const mapRSStoEntry = (
rssItem: RSSItem,
Expand Down
1 change: 1 addition & 0 deletions server/typedefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const typeDefs = gql`
title: String!
link: String!
lastFetched: Date!
feedURL: String!
}
type Activity {
Expand Down
2 changes: 2 additions & 0 deletions server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export enum EntryFilter {

export type Feed = {
__typename?: "Feed";
feedURL: Scalars["String"];
id: Scalars["ID"];
lastFetched: Scalars["Date"];
link: Scalars["String"];
Expand Down Expand Up @@ -250,6 +251,7 @@ export type FeedResolvers<
ContextType = any,
ParentType extends ResolversParentTypes["Feed"] = ResolversParentTypes["Feed"]
> = {
feedURL?: Resolver<ResolversTypes["String"], ParentType, ContextType>;
id?: Resolver<ResolversTypes["ID"], ParentType, ContextType>;
lastFetched?: Resolver<ResolversTypes["Date"], ParentType, ContextType>;
link?: Resolver<ResolversTypes["String"], ParentType, ContextType>;
Expand Down

1 comment on commit af3f9d4

@vercel
Copy link

@vercel vercel bot commented on af3f9d4 Sep 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.