diff --git a/src/components/posts/ClientViewProviderPosts.tsx b/src/components/posts/ClientViewProviderPosts.tsx index f8dc3557..d836e432 100644 --- a/src/components/posts/ClientViewProviderPosts.tsx +++ b/src/components/posts/ClientViewProviderPosts.tsx @@ -17,7 +17,8 @@ interface ProviderPost { user_id: string; content: string; id: number; - category: string; + //TODO: update this to allow a list of Subjects + subject: string; title: string; seller_name: string; major_municipality: string; @@ -49,11 +50,11 @@ export const ClientViewProviderPosts: Component = (props) => { const newItems = await Promise.all( data?.map(async (item) => { productCategories.forEach((productCategories) => { - if (item.product_category.toString() === productCategories.id) { - item.category = productCategories.name; + if (item.product_subject.toString() === productCategories.id) { + item.subject = productCategories.name; } }); - delete item.product_category; + delete item.product_subject; if (item.price_id !== null) { const priceData = await stripe.prices.retrieve(item.price_id); diff --git a/src/components/posts/FullPostView.tsx b/src/components/posts/FullPostView.tsx index 0004ee3b..dbdb3323 100644 --- a/src/components/posts/FullPostView.tsx +++ b/src/components/posts/FullPostView.tsx @@ -19,7 +19,7 @@ const productCategories = values.productCategoryInfo.categories interface Post { content: string; id: number; - category: string; + subject: string; title: string; seller_name: string; major_municipality: string; @@ -68,11 +68,11 @@ export const ViewFullPost: Component = (props) => { } else { data?.map(async (item) => { productCategories.forEach(productCategories => { - if (item.product_category.toString() === productCategories.id) { - item.category = productCategories.name + if (item.product_subject.toString() === productCategories.id) { + item.subject = productCategories.name } }) - delete item.product_category + delete item.product_subject item.seller_url = `/${lang}/provider/${item.seller_id}` }) setPost(data[0]); @@ -305,7 +305,7 @@ export const ViewFullPost: Component = (props) => { {t('postLabels.location')}{post()?.major_municipality}/{post()?.minor_municipality}/ {post()?.governing_district}

-

{t('postLabels.category')}{post()?.category}

+

{t('postLabels.category')}{post()?.subject}

{t('buttons.contact')} diff --git a/src/components/posts/ViewProviderPosts.tsx b/src/components/posts/ViewProviderPosts.tsx index 08926a39..86c2f4e6 100644 --- a/src/components/posts/ViewProviderPosts.tsx +++ b/src/components/posts/ViewProviderPosts.tsx @@ -18,7 +18,7 @@ const productCategories = values.productCategoryInfo.categories; interface ProviderPost { content: string; id: number; - category: string; + subject: string; title: string; seller_name: string; major_municipality: string; @@ -61,11 +61,11 @@ export const ViewProviderPosts: Component = () => { const newItems = await Promise.all( data?.map(async (item) => { productCategories.forEach((productCategories) => { - if (item.product_category.toString() === productCategories.id) { - item.category = productCategories.name; + if (item.product_subject.toString() === productCategories.id) { + item.subject = productCategories.name; } }); - delete item.product_category; + delete item.product_subject; if (item.price_id !== null) { const priceData = await stripe.prices.retrieve(item.price_id); diff --git a/src/components/posts/fetchPosts.ts b/src/components/posts/fetchPosts.ts index 0d1e1f75..bda4ee7f 100644 --- a/src/components/posts/fetchPosts.ts +++ b/src/components/posts/fetchPosts.ts @@ -11,7 +11,7 @@ export async function fetchFilteredPosts(categoryFilters: Array, locatio try { let query = supabase.from("sellerposts").select("*"); if(categoryFilters.length !== 0) { - query = query.in('product_category', categoryFilters); + query = query.in('product_subject', categoryFilters); } if(locationFilters.length !== 0) { query = query.in('major_municipality', locationFilters); diff --git a/src/components/services/CategoryCarousel.tsx b/src/components/services/CategoryCarousel.tsx index 538f085e..0a420984 100644 --- a/src/components/services/CategoryCarousel.tsx +++ b/src/components/services/CategoryCarousel.tsx @@ -32,7 +32,7 @@ import { doc } from "prettier"; let categories: Array = []; -const { data, error } = await supabase.from("post_category").select("*"); +const { data, error } = await supabase.from("post_subject").select("*"); if (error) { console.log("supabase error: " + error.message); diff --git a/src/components/services/ServicesMain.tsx b/src/components/services/ServicesMain.tsx index 8b09676d..70723306 100644 --- a/src/components/services/ServicesMain.tsx +++ b/src/components/services/ServicesMain.tsx @@ -47,7 +47,7 @@ if (user.session === null || user.session === undefined) { interface ProviderPost { content: string; id: number; - category: string; + subject: string; title: string; seller_name: string; major_municipality: string; @@ -96,11 +96,11 @@ export const ServicesView: Component = () => { const newItems = await Promise.all( data?.map(async (item) => { productCategories.forEach((productCategories) => { - if (item.product_category.toString() === productCategories.id) { - item.category = productCategories.name; + if (item.product_subject.toString() === productCategories.id) { + item.subject = productCategories.name; } }); - delete item.product_category; + delete item.product_subject; if (item.price_id !== null) { const priceData = await stripe.prices.retrieve(item.price_id); @@ -182,11 +182,11 @@ export const ServicesView: Component = () => { //Add the categories to the posts in the current language allPosts?.map((item) => { productCategories.forEach((productCategories) => { - if (item.product_category.toString() === productCategories.id) { - item.category = productCategories.name; + if (item.product_subject.toString() === productCategories.id) { + item.subject = productCategories.name; } }); - delete item.product_category; + delete item.product_subject; }); setPosts(allPosts!); @@ -200,11 +200,11 @@ export const ServicesView: Component = () => { res.map((post) => { productCategories.forEach((productCategory) => { - if (post.product_category.toString() === productCategory.id) { - post.category = productCategory.name; + if (post.product_subject.toString() === productCategory.id) { + post.subject = productCategory.name; } }); - delete post.product_category; + delete post.product_subject; }); setPosts(res); diff --git a/src/components/services/ViewCard.tsx b/src/components/services/ViewCard.tsx index 7a665d31..974951b6 100644 --- a/src/components/services/ViewCard.tsx +++ b/src/components/services/ViewCard.tsx @@ -15,7 +15,7 @@ const t = useTranslations(lang); interface Post { content: string; id: number; - category: string; + subject: string; title: string; seller_name: string; major_municipality: string; @@ -120,9 +120,9 @@ export const ViewCard: Component = (props) => { userId={post.user_id} postImage={post.image_urls} /> +
-

{post.title} diff --git a/src/pages/api/providerCreatePost.ts b/src/pages/api/providerCreatePost.ts index 1491e39d..f084d3c2 100644 --- a/src/pages/api/providerCreatePost.ts +++ b/src/pages/api/providerCreatePost.ts @@ -18,7 +18,7 @@ export const POST: APIRoute = async ({ request, redirect }) => { const access_token = formData.get("access_token"); const refresh_token = formData.get("refresh_token"); const title = formData.get("Title"); - const serviceCategory = formData.get("ServiceCategory"); + const subject = formData.get("Subject"); const content = formData.get("Content"); const country = formData.get("country"); const tax_code = formData.get("TaxCode"); @@ -31,7 +31,7 @@ export const POST: APIRoute = async ({ request, redirect }) => { // Validate the formData - you'll probably want to do more than this if ( !title || - !serviceCategory || + !subject || !content || !country || !tax_code @@ -137,11 +137,11 @@ export const POST: APIRoute = async ({ request, redirect }) => { ); } - const { data: categoryId, error: categoryError } = await supabase - .from("post_category") + const { data: subjectId, error: subjectError } = await supabase + .from("post_subject") .select("id") - .eq("id", serviceCategory); - if (categoryError) { + .eq("id", subject); + if (subjectError) { return new Response( JSON.stringify({ message: t("apiErrors.noCategory"), @@ -176,7 +176,7 @@ export const POST: APIRoute = async ({ request, redirect }) => { title: title, content: content, location: location[0].id, - product_category: categoryId[0].id, + product_subject: subjectId[0].id, image_urls: imageUrl, user_id: user.id, }; diff --git a/supabase/migrations/20240327194919_subjectFilter.sql b/supabase/migrations/20240327194919_subjectFilter.sql new file mode 100644 index 00000000..47f1b405 --- /dev/null +++ b/supabase/migrations/20240327194919_subjectFilter.sql @@ -0,0 +1,172 @@ +drop policy "Enable select for authenticated users only" on "public"."post_category"; + +revoke delete on table "public"."post_category" from "anon"; + +revoke insert on table "public"."post_category" from "anon"; + +revoke references on table "public"."post_category" from "anon"; + +revoke select on table "public"."post_category" from "anon"; + +revoke trigger on table "public"."post_category" from "anon"; + +revoke truncate on table "public"."post_category" from "anon"; + +revoke update on table "public"."post_category" from "anon"; + +revoke delete on table "public"."post_category" from "authenticated"; + +revoke insert on table "public"."post_category" from "authenticated"; + +revoke references on table "public"."post_category" from "authenticated"; + +revoke select on table "public"."post_category" from "authenticated"; + +revoke trigger on table "public"."post_category" from "authenticated"; + +revoke truncate on table "public"."post_category" from "authenticated"; + +revoke update on table "public"."post_category" from "authenticated"; + +revoke delete on table "public"."post_category" from "service_role"; + +revoke insert on table "public"."post_category" from "service_role"; + +revoke references on table "public"."post_category" from "service_role"; + +revoke select on table "public"."post_category" from "service_role"; + +revoke trigger on table "public"."post_category" from "service_role"; + +revoke truncate on table "public"."post_category" from "service_role"; + +revoke update on table "public"."post_category" from "service_role"; + +alter table "public"."seller_post" drop constraint "seller_post_product_category_fkey"; + +alter table "public"."post_category" drop constraint "post_category_id_key"; + +alter table "public"."post_category" drop constraint "post_category_language_fkey"; + +alter table "public"."post_category" drop constraint "post_category_pkey"; + +drop index if exists "public"."post_category_id_key"; + +drop index if exists "public"."post_category_pkey"; + +drop table "public"."post_category"; + +create table "public"."post_subject" ( + "id" bigint generated by default as identity not null, + "subject" text not null, + "language" bigint not null +); + + +alter table "public"."post_subject" enable row level security; + +alter table "public"."seller_post" drop column "product_category" CASCADE; + +alter table "public"."seller_post" add column "product_subject" text[] not null; + +CREATE UNIQUE INDEX post_subject_id_key ON public.post_subject USING btree (id); + +CREATE UNIQUE INDEX post_subject_pkey ON public.post_subject USING btree (id); + +alter table "public"."post_subject" add constraint "post_subject_pkey" PRIMARY KEY using index "post_subject_pkey"; + +alter table "public"."post_subject" add constraint "post_subject_id_key" UNIQUE using index "post_subject_id_key"; + +alter table "public"."post_subject" add constraint "post_subject_language_fkey" FOREIGN KEY (language) REFERENCES language(id) not valid; + +alter table "public"."post_subject" validate constraint "post_subject_language_fkey"; + +-- alter table "public"."seller_post" add constraint "seller_post_product_subject_fkey" FOREIGN KEY (product_subject) REFERENCES post_subject(id) not valid; + +-- alter table "public"."seller_post" validate constraint "seller_post_product_subject_fkey"; + +create or replace view "public"."sellerposts" as SELECT seller_post.id, + seller_post.title, + seller_post.content, + seller_post.user_id, + seller_post.image_urls, + seller_post.product_subject, + locationview.major_municipality, + locationview.minor_municipality, + locationview.governing_district, + sellers.seller_name, + sellers.seller_id, + profiles.email, + seller_post.stripe_price_id AS price_id, + seller_post.stripe_product_id AS product_id + FROM (((seller_post + LEFT JOIN profiles ON ((seller_post.user_id = profiles.user_id))) + LEFT JOIN sellers ON ((seller_post.user_id = sellers.user_id))) + LEFT JOIN locationview ON ((seller_post.location = locationview.id))); + +CREATE OR REPLACE FUNCTION "public"."title_content"("public"."sellerposts") RETURNS "text" + LANGUAGE "sql" IMMUTABLE + AS $_$ + select $1.title || ' ' || $1.content; +$_$; + +grant delete on table "public"."post_subject" to "anon"; + +grant insert on table "public"."post_subject" to "anon"; + +grant references on table "public"."post_subject" to "anon"; + +grant select on table "public"."post_subject" to "anon"; + +grant trigger on table "public"."post_subject" to "anon"; + +grant truncate on table "public"."post_subject" to "anon"; + +grant update on table "public"."post_subject" to "anon"; + +grant delete on table "public"."post_subject" to "authenticated"; + +grant insert on table "public"."post_subject" to "authenticated"; + +grant references on table "public"."post_subject" to "authenticated"; + +grant select on table "public"."post_subject" to "authenticated"; + +grant trigger on table "public"."post_subject" to "authenticated"; + +grant truncate on table "public"."post_subject" to "authenticated"; + +grant update on table "public"."post_subject" to "authenticated"; + +grant delete on table "public"."post_subject" to "service_role"; + +grant insert on table "public"."post_subject" to "service_role"; + +grant references on table "public"."post_subject" to "service_role"; + +grant select on table "public"."post_subject" to "service_role"; + +grant trigger on table "public"."post_subject" to "service_role"; + +grant truncate on table "public"."post_subject" to "service_role"; + +grant update on table "public"."post_subject" to "service_role"; + +create policy "Enable select for authenticated users only" +on "public"."post_subject" +as permissive +for select +to authenticated +using (true); + + + +-- alter table "public"."seller_post"drop constraint"seller_post_product_subject_fkey"; + +-- drop view if exists"public"."sellerposts" cascade; + +-- alter table "public"."seller_post" alter column "product_subject" set data type text[] using "product_subject"::text[]; + + + + diff --git a/supabase/seed.sql b/supabase/seed.sql index 5125ceb1..a009f48e 100644 --- a/supabase/seed.sql +++ b/supabase/seed.sql @@ -1,4 +1,3 @@ - -- -- Data for Name: users; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin -- @@ -105,7 +104,7 @@ INSERT INTO "public"."clients" ("user_id", "created_at", "location", "client_pho -- Data for Name: post_category; Type: TABLE DATA; Schema: public; Owner: postgres -- -INSERT INTO "public"."post_category" ("id", "category", "language") VALUES +INSERT INTO "public"."post_subject" ("id", "subject", "language") VALUES (1, 'k6', 1), (2, 'k10', 1), (3, 'k12', 1), @@ -133,16 +132,16 @@ INSERT INTO "public"."profiles" ("created_at", "first_name", "last_name", "user_ -- Data for Name: seller_post; Type: TABLE DATA; Schema: public; Owner: postgres -- -INSERT INTO "public"."seller_post" ("id", "created_at", "title", "product_category", "content", "location", "user_id", "image_urls", "stripe_price_id", "stripe_product_id") VALUES - (1, '2024-03-05 15:38:02.509065+00', 'Test Post 1', 1, 'Content of the first post', 1, '84a298b6-9caf-4305-9bfe-3ea325df9188', NULL, 'price_1OtG6cBRZLMDvS4Ri22IpzGq', 'prod_PihVI0liGFkala'), - (5, '2024-03-05 21:53:47.560102+00', 'Geography course', 2, 'k10 geography course', 1, '84a298b6-9caf-4305-9bfe-3ea325df9188', NULL, 'price_1OtFqrBRZLMDvS4RK5Ajf7na', 'prod_PihF0aDvvT4PeU'), - (3, '2024-03-05 21:52:06.919336+00', 'Math course', 3, 'math course for k12', 1, '84a298b6-9caf-4305-9bfe-3ea325df9188', NULL, 'price_1OtFmkBRZLMDvS4RJ8TNXGrH', 'prod_PihB8lq2HWY15J'), - (2, '2024-03-05 15:40:05.243892+00', 'Test Post 2', 1, 'Content for the second post', 1, '84a298b6-9caf-4305-9bfe-3ea325df9188', NULL, 'price_1OtFjpBRZLMDvS4RPoOg78AS', 'prod_Pih8Qrjfpr0Zmo'), - (6, '2024-03-05 21:54:44.695358+00', 'programming course ', 3, 'learn programming', 1, 'a23376db-215d-49c4-9d9d-791c26579543', NULL, 'price_1OtFmFBRZLMDvS4RsYXD3Q3C', 'prod_PihAqPK24WxqZp'), - (7, '2024-03-27 14:25:37.137856+00', 'Test', 7, '

This post is for testing provider images in the cart and also longer post content so here is some more content to see if the cards properly cut off after three lines like we expect? Is this working? Test Test Test TESt testing Test

', 6, 'b78eab21-c34e-41ef-9a72-64ee49f4cbc0', '0.1236654180882113.svg,0.7931177438497017.svg,0.7728585086209605.svg', 'price_1OyxQ5BRZLMDvS4RJ1oWeAIj', 'prod_PoabbRuN1tqxj0'), - (10, '2024-03-27 15:49:08.243995+00', 'Testing testing', 5, '

test

', 11, 'b00f3d62-4eb1-40ba-b73e-e3dc78eff08a', NULL, 'price_1OyyiuBRZLMDvS4Rpb0hhUK3', 'prod_PobwysGlI4L0OK'), - (11, '2024-03-27 15:50:36.102267+00', 'New Test', 6, '

Test

', 12, 'b00f3d62-4eb1-40ba-b73e-e3dc78eff08a', NULL, 'price_1OyykKBRZLMDvS4RC4SRSDLb', 'prod_PobyNSYyDLZArR'), - (12, '2024-03-27 15:53:32.292584+00', 'Another test', 4, '

test

', 13, 'b00f3d62-4eb1-40ba-b73e-e3dc78eff08a', NULL, 'price_1OyynABRZLMDvS4RMi5Z83UK', 'prod_Poc1Kl6ObNXQ89'); + INSERT INTO "public"."seller_post" ("id", "created_at", "title", "product_subject", "content", "location", "user_id", "image_urls", "stripe_price_id", "stripe_product_id") VALUES + (1, '2024-03-05 15:38:02.509065+00', 'Test Post 1', '{"1"}', 'Content of the first post', 1, '84a298b6-9caf-4305-9bfe-3ea325df9188', NULL, 'price_1OtG6cBRZLMDvS4Ri22IpzGq', 'prod_PihVI0liGFkala'), + (5, '2024-03-05 21:53:47.560102+00', 'Geography course', '{"2"}', 'k10 geography course', 1, '84a298b6-9caf-4305-9bfe-3ea325df9188', NULL, 'price_1OtFqrBRZLMDvS4RK5Ajf7na', 'prod_PihF0aDvvT4PeU'), + (3, '2024-03-05 21:52:06.919336+00', 'Math course', '{"3"}', 'math course for k12', 1, '84a298b6-9caf-4305-9bfe-3ea325df9188', NULL, 'price_1OtFmkBRZLMDvS4RJ8TNXGrH', 'prod_PihB8lq2HWY15J'), + (2, '2024-03-05 15:40:05.243892+00', 'Test Post 2', '{"1"}', 'Content for the second post', 1, '84a298b6-9caf-4305-9bfe-3ea325df9188', NULL, 'price_1OtFjpBRZLMDvS4RPoOg78AS', 'prod_Pih8Qrjfpr0Zmo'), + (6, '2024-03-05 21:54:44.695358+00', 'programming course ', '{"3"}', 'learn programming', 1, 'a23376db-215d-49c4-9d9d-791c26579543', NULL, 'price_1OtFmFBRZLMDvS4RsYXD3Q3C', 'prod_PihAqPK24WxqZp'), + (7, '2024-03-27 14:25:37.137856+00', 'Test', '{"7"}', '

This post is for testing provider images in the cart and also longer post content so here is some more content to see if the cards properly cut off after three lines like we expect? Is this working? Test Test Test TESt testing Test

', 6, 'b78eab21-c34e-41ef-9a72-64ee49f4cbc0', '0.1236654180882113.svg,0.7931177438497017.svg,0.7728585086209605.svg', 'price_1OyxQ5BRZLMDvS4RJ1oWeAIj', 'prod_PoabbRuN1tqxj0'), + (10, '2024-03-27 15:49:08.243995+00', 'Testing testing', '{"5"}', '

test

', 11, 'b00f3d62-4eb1-40ba-b73e-e3dc78eff08a', NULL, 'price_1OyyiuBRZLMDvS4Rpb0hhUK3', 'prod_PobwysGlI4L0OK'), + (11, '2024-03-27 15:50:36.102267+00', 'New Test', '{"6"}', '

Test

', 12, 'b00f3d62-4eb1-40ba-b73e-e3dc78eff08a', NULL, 'price_1OyykKBRZLMDvS4RC4SRSDLb', 'prod_PobyNSYyDLZArR'), + (12, '2024-03-27 15:53:32.292584+00', 'Another test', '{"4"}', '

test

', 13, 'b00f3d62-4eb1-40ba-b73e-e3dc78eff08a', NULL, 'price_1OyynABRZLMDvS4RMi5Z83UK', 'prod_Poc1Kl6ObNXQ89'); -- @@ -150,7 +149,7 @@ INSERT INTO "public"."seller_post" ("id", "created_at", "title", "product_catego -- INSERT INTO "public"."sellers" ("created_at", "seller_name", "user_id", "location", "seller_phone", "image_url", "seller_id", "language_spoken", "stripe_connected_account_id") VALUES - ('2024-03-05 15:42:34.225911+00', 'German', '84a298b6-9caf-4305-9bfe-3ea325df9188', 1, '00010001', NULL, 3, '{english}', NULL), + ('2024-03-05 15:42:34.225911+00', 'German', '84a298b6-9caf-4305-9bfe-3ea325df9188', 1, '00010001', NULL, 3, NULL, NULL), ('2024-03-19 19:37:25.638743+00', 'test test', 'a23376db-215d-49c4-9d9d-791c26579543', 2, '16529658956', NULL, 4, NULL, 'acct_1Ow8TSB0tPFjRwUY'), ('2024-03-26 13:43:48.52652+00', 'Test2 Test', 'ec946adf-7315-4721-a238-ed600dd153d7', 3, '11234567890', NULL, 5, NULL, 'acct_1OyaI4B1rj93e0iW'), ('2024-03-26 21:49:40.736227+00', 'Test test', 'df188225-8970-42a4-a54f-97b303c2b2ed', 4, '11324567890', NULL, 6, NULL, 'acct_1OyhsGBGXYM1FOiH'), @@ -218,7 +217,7 @@ SELECT pg_catalog.setval('"public"."minor_municipality_id_seq"', 1, false); -- Name: post_category_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres -- -SELECT pg_catalog.setval('"public"."post_category_id_seq"', 3, true); +SELECT pg_catalog.setval('"public"."post_subject_id_seq"', 3, true); --