diff --git a/src/components/posts/CreateNewPost.tsx b/src/components/posts/CreateNewPost.tsx index 92a906b2..4bd82280 100644 --- a/src/components/posts/CreateNewPost.tsx +++ b/src/components/posts/CreateNewPost.tsx @@ -147,11 +147,11 @@ export const CreateNewPost: Component = () => { }); }); - createEffect(() => { - if(selectedTaxCode() !== undefined) { - console.log("Tax Code: " + selectedTaxCode()!.value); - } - }); + // createEffect(() => { + // if(selectedTaxCode() !== undefined) { + // console.log("Tax Code: " + selectedTaxCode()!.value); + // } + // }); createEffect(async () => { const { data, error } = await supabase.auth.getSession(); @@ -170,7 +170,9 @@ export const CreateNewPost: Component = () => { if (providers.length === 0) { alert(t("messages.onlyProvider")); window.location.href = `/${lang}/provider/createaccount`; - } else { + } else if (providers[0].stripe_connected_account_id === null) { + alert(t("messages.noStripeAccount")); + window.location.href = `/${lang}/provider/profile`; } } } catch (error) { diff --git a/src/components/users/ClientRegistration.tsx b/src/components/users/ClientRegistration.tsx index 46645ade..5db07637 100644 --- a/src/components/users/ClientRegistration.tsx +++ b/src/components/users/ClientRegistration.tsx @@ -38,8 +38,6 @@ export const ClientRegistration: Component = () => { const [firstName, setFirstName] = createSignal(""); const [lastName, setLastName] = createSignal(""); - const regularExpressionPhone = new RegExp("^[0-9]{8}$"); - createEffect(async () => { const { data, error } = await supabase.auth.getSession(); setSession(data.session); @@ -116,97 +114,6 @@ export const ClientRegistration: Component = () => { console.log("Other error: " + error); } - // //Minor Municipality - // try { - // const { data: minorMunicipality, error: errorMinorMunicipality } = - // await supabase.from("minor_municipality").select("*"); - // if (errorMinorMunicipality) { - // console.log("supabase error: " + errorMinorMunicipality.message); - // } else { - // document - // .getElementById("MajorMunicipality") - // ?.addEventListener("change", () => { - // let municipalitySelect = document.getElementById( - // "MinorMunicipality" - // ) as HTMLSelectElement; - // - // let length = municipalitySelect?.length; - // - // for (let i = length - 1; i > -1; i--) { - // if (municipalitySelect.options[i].value !== "") { - // municipalitySelect.remove(i); - // } - // } - // - // let filteredMunicipality = minorMunicipality.filter( - // (municipality) => - // municipality.major_municipality == - // ( - // document.getElementById( - // "MajorMunicipality" - // ) as HTMLSelectElement - // )?.value - // ); - // filteredMunicipality.forEach((municipality) => { - // let municipalityOption = new Option( - // municipality.minor_municipality, - // municipality.id - // ); - // document - // .getElementById("MinorMunicipality") - // ?.append(municipalityOption); - // }); - // }); - // } - // } catch (error) { - // console.log("Other error: " + error); - // } - // - // //Governing District - // try { - // const { data: governingDistrict, error: errorGoverningDistrict } = - // await supabase.from("governing_district").select("*"); - // if (errorGoverningDistrict) { - // console.log("supabase error: " + errorGoverningDistrict.message); - // } else { - // document - // .getElementById("MinorMunicipality") - // ?.addEventListener("change", () => { - // let districtSelect = document.getElementById( - // "GoverningDistrict" - // ) as HTMLSelectElement; - // - // let length = districtSelect?.length; - // - // for (let i = length - 1; i > -1; i--) { - // if (districtSelect.options[i].value !== "") { - // districtSelect.remove(i); - // } - // } - // - // let filteredDistrict = governingDistrict.filter( - // (district) => - // district.minor_municipality == - // ( - // document.getElementById( - // "MinorMunicipality" - // ) as HTMLSelectElement - // )?.value - // ); - // filteredDistrict.forEach((district) => { - // let districtOption = new Option( - // district.governing_district, - // district.id - // ); - // document - // .getElementById("GoverningDistrict") - // ?.append(districtOption); - // }); - // }); - // } - // } catch (error) { - // console.log("Other error: " + error); - // } } else { alert(t("messages.createClientAccount")); location.href = `/${lang}/login`; diff --git a/src/components/users/ProviderProfileView.tsx b/src/components/users/ProviderProfileView.tsx index 5d1d2113..01518336 100644 --- a/src/components/users/ProviderProfileView.tsx +++ b/src/components/users/ProviderProfileView.tsx @@ -16,6 +16,7 @@ import UserImage from "./UserImage"; import { ui } from "../../i18n/ui"; import type { uiObject } from "../../i18n/uiType"; import { getLangFromUrl, useTranslations } from "../../i18n/utils"; +import { StripeButton } from "./provider/StripeButton"; const lang = getLangFromUrl(new URL(window.location.href)); const t = useTranslations(lang); @@ -118,7 +119,7 @@ export const ProviderProfileView: Component = () => { if (session()) { try { const { data, error } = await supabase - .from("providerview") + .from("sellerview") .select("*") .eq("user_id", user_id); console.log(data); @@ -127,29 +128,29 @@ export const ProviderProfileView: Component = () => { console.log(error); } else if (data[0] === undefined) { alert(t("messages.noProvider")); - location.href = `/${lang}/services`; + location.href = `/${lang}/provider/createaccount`; } else { - let languageArray = data[0].language_spoken; - console.log("Languages Array: " + languageArray); - languageArray?.map((language: number) => { - if (language == 1) { - setLanguageSpoken([...languageSpoken(), "English"]); - } + // let languageArray = data[0].language_spoken; + // console.log("Languages Array: " + languageArray); + // languageArray?.map((language: number) => { + // if (language == 1) { + // setLanguageSpoken([...languageSpoken(), "English"]); + // } - if (language == 2) { - setLanguageSpoken([...languageSpoken(), "Español"]); - } + // if (language == 2) { + // setLanguageSpoken([...languageSpoken(), "Español"]); + // } - if (language == 3) { - setLanguageSpoken([...languageSpoken(), "Français"]); - } - }); + // if (language == 3) { + // setLanguageSpoken([...languageSpoken(), "Français"]); + // } + // }); - //set initial list of languages for provider - setLanguagePick(data[0].language_spoken); + // //set initial list of languages for provider + // setLanguagePick(data[0].language_spoken); - //set display list of languages for provider - data[0].languages = languageSpoken().join(", "); + // //set display list of languages for provider + // data[0].languages = languageSpoken().join(", "); setProvider(data[0]); } @@ -217,30 +218,30 @@ export const ProviderProfileView: Component = () => { } //Will create a list of Languages in the database - try { - const { data, error } = await supabase.from("language").select("*"); - if (error) { - console.log("supabase error: " + error.message); - } else if (data!) { - console.log("DB data"); - console.log(data); - data.forEach((item) => { - item.checked = false; - if (provider()?.language_spoken && provider()?.language_spoken.length > 0){ - provider()?.language_spoken.forEach((language) => { - console.log(language); - if (language === item.id.toString()) { - item.checked = true; - } - }); - } - }); - console.log(data); - setLanguages(data); - } - } catch (error) { - console.log("Language error: " + error); - } + // try { + // const { data, error } = await supabase.from("language").select("*"); + // if (error) { + // console.log("supabase error: " + error.message); + // } else if (data!) { + // console.log("DB data"); + // console.log(data); + // data.forEach((item) => { + // item.checked = false; + // if (provider()?.language_spoken && provider()?.language_spoken.length > 0){ + // provider()?.language_spoken.forEach((language) => { + // console.log(language); + // if (language === item.id.toString()) { + // item.checked = true; + // } + // }); + // } + // }); + // console.log(data); + // setLanguages(data); + // } + // } catch (error) { + // console.log("Language error: " + error); + // } //Will create a list of Major Municipalities based on the selected country try { @@ -283,96 +284,96 @@ export const ProviderProfileView: Component = () => { } //Creates drop down options for Minor Municipality based on selected Major Municipality - try { - const { data: minorMunicipality, error: errorMinorMunicipality } = - await supabase.from("minor_municipality").select("*"); - if (errorMinorMunicipality) { - console.log("supabase error: " + errorMinorMunicipality.message); - } else { - document - .getElementById("MajorMunicipality") - ?.addEventListener("change", () => { - let municipalitySelect = document.getElementById( - "MinorMunicipality" - ) as HTMLSelectElement; - - let length = municipalitySelect?.length; - - for (let i = length - 1; i > -1; i--) { - if (municipalitySelect.options[i].value !== "") { - municipalitySelect.remove(i); - } - } - - let filteredMunicipality = minorMunicipality.filter( - (municipality) => - municipality.major_municipality == - ( - document.getElementById( - "MajorMunicipality" - ) as HTMLSelectElement - )?.value - ); - filteredMunicipality.forEach((municipality) => { - let municipalityOption = new Option( - municipality.minor_municipality, - municipality.id - ); - document - .getElementById("MinorMunicipality") - ?.append(municipalityOption); - }); - }); - } - } catch (error) { - console.log("Other error: " + error); - } + // try { + // const { data: minorMunicipality, error: errorMinorMunicipality } = + // await supabase.from("minor_municipality").select("*"); + // if (errorMinorMunicipality) { + // console.log("supabase error: " + errorMinorMunicipality.message); + // } else { + // document + // .getElementById("MajorMunicipality") + // ?.addEventListener("change", () => { + // let municipalitySelect = document.getElementById( + // "MinorMunicipality" + // ) as HTMLSelectElement; + + // let length = municipalitySelect?.length; + + // for (let i = length - 1; i > -1; i--) { + // if (municipalitySelect.options[i].value !== "") { + // municipalitySelect.remove(i); + // } + // } + + // let filteredMunicipality = minorMunicipality.filter( + // (municipality) => + // municipality.major_municipality == + // ( + // document.getElementById( + // "MajorMunicipality" + // ) as HTMLSelectElement + // )?.value + // ); + // filteredMunicipality.forEach((municipality) => { + // let municipalityOption = new Option( + // municipality.minor_municipality, + // municipality.id + // ); + // document + // .getElementById("MinorMunicipality") + // ?.append(municipalityOption); + // }); + // }); + // } + // } catch (error) { + // console.log("Other error: " + error); + // } //Creates filtered drop down options for Governing District base on selected Minor Municipality - try { - const { data: governingDistrict, error: errorGoverningDistrict } = - await supabase.from("governing_district").select("*"); - if (errorGoverningDistrict) { - console.log("supabase error: " + errorGoverningDistrict.message); - } else { - document - .getElementById("MinorMunicipality") - ?.addEventListener("change", () => { - let districtSelect = document.getElementById( - "GoverningDistrict" - ) as HTMLSelectElement; - - let length = districtSelect?.length; - - for (let i = length - 1; i > -1; i--) { - if (districtSelect.options[i].value !== "") { - districtSelect.remove(i); - } - } - - let filteredDistrict = governingDistrict.filter( - (district) => - district.minor_municipality == - ( - document.getElementById( - "MinorMunicipality" - ) as HTMLSelectElement - )?.value - ); - filteredDistrict.forEach((district) => { - let districtOption = new Option( - district.governing_district, - district.id - ); - document - .getElementById("GoverningDistrict") - ?.append(districtOption); - }); - }); - } - } catch (error) { - console.log("Other error: " + error); - } + // try { + // const { data: governingDistrict, error: errorGoverningDistrict } = + // await supabase.from("governing_district").select("*"); + // if (errorGoverningDistrict) { + // console.log("supabase error: " + errorGoverningDistrict.message); + // } else { + // document + // .getElementById("MinorMunicipality") + // ?.addEventListener("change", () => { + // let districtSelect = document.getElementById( + // "GoverningDistrict" + // ) as HTMLSelectElement; + + // let length = districtSelect?.length; + + // for (let i = length - 1; i > -1; i--) { + // if (districtSelect.options[i].value !== "") { + // districtSelect.remove(i); + // } + // } + + // let filteredDistrict = governingDistrict.filter( + // (district) => + // district.minor_municipality == + // ( + // document.getElementById( + // "MinorMunicipality" + // ) as HTMLSelectElement + // )?.value + // ); + // filteredDistrict.forEach((district) => { + // let districtOption = new Option( + // district.governing_district, + // district.id + // ); + // document + // .getElementById("GoverningDistrict") + // ?.append(districtOption); + // }); + // }); + // } + // } catch (error) { + // console.log("Other error: " + error); + // } //If the user is not signed in then tell them to sign in and send them to the login page } @@ -385,33 +386,33 @@ export const ProviderProfileView: Component = () => { const majorMunicipality = document.getElementById( "MajorMunicipality" ) as HTMLSelectElement; - const minorMunicipality = document.getElementById( - "MinorMunicipality" - ) as HTMLSelectElement; - const governingDistrict = document.getElementById( - "GoverningDistrict" - ) as HTMLSelectElement; + // const minorMunicipality = document.getElementById( + // "MinorMunicipality" + // ) as HTMLSelectElement; + // const governingDistrict = document.getElementById( + // "GoverningDistrict" + // ) as HTMLSelectElement; if ( country.value !== "" || - majorMunicipality.value !== "" || - minorMunicipality.value !== "" || - governingDistrict.value !== "" + majorMunicipality.value !== "" + // minorMunicipality.value !== "" || + // governingDistrict.value !== "" ) { country.required = true; majorMunicipality.required = true; - minorMunicipality.required = true; - governingDistrict.required = true; + // minorMunicipality.required = true; + // governingDistrict.required = true; } else if ( country.value === "" && - majorMunicipality.value === "" && - minorMunicipality.value === "" && - governingDistrict.value === "" + majorMunicipality.value === "" + // minorMunicipality.value === "" && + // governingDistrict.value === "" ) { country.required = false; majorMunicipality.required = false; - minorMunicipality.required = false; - governingDistrict.required = false; + // minorMunicipality.required = false; + // governingDistrict.required = false; } }; @@ -432,48 +433,49 @@ export const ProviderProfileView: Component = () => { setFormData(formData); } - let expanded = false; - function languageCheckboxes() { - let checkboxes = document.getElementById("checkboxes"); - if (!expanded) { - checkboxes?.classList.remove("hidden"); - checkboxes?.classList.add("block"); - expanded = true; - } else { - checkboxes?.classList.remove("block"); - checkboxes?.classList.add("hidden"); - expanded = false; - } - } - - function setLanguageArray(e: Event) { - if ((e.target as HTMLInputElement).checked) { - setLanguagePick([ - ...languagePick(), - (e.target as HTMLInputElement).value, - ]); - } else if ((e.target as HTMLInputElement).checked === false) { - if (languagePick().includes((e.target as HTMLInputElement).value)) { - setLanguagePick( - languagePick().filter( - (value) => value !== (e.target as HTMLInputElement).value - ) - ); - } - } - if (languagePick().length > 0) { - document.getElementById("isValid")?.classList.remove("hidden"); - } else if (languagePick().length === 0) { - document.getElementById("isValid")?.classList.add("hidden"); - } - console.log(languagePick()); - } + // let expanded = false; + // function languageCheckboxes() { + // let checkboxes = document.getElementById("checkboxes"); + // if (!expanded) { + // checkboxes?.classList.remove("hidden"); + // checkboxes?.classList.add("block"); + // expanded = true; + // } else { + // checkboxes?.classList.remove("block"); + // checkboxes?.classList.add("hidden"); + // expanded = false; + // } + // } + + // function setLanguageArray(e: Event) { + // if ((e.target as HTMLInputElement).checked) { + // setLanguagePick([ + // ...languagePick(), + // (e.target as HTMLInputElement).value, + // ]); + // } else if ((e.target as HTMLInputElement).checked === false) { + // if (languagePick().includes((e.target as HTMLInputElement).value)) { + // setLanguagePick( + // languagePick().filter( + // (value) => value !== (e.target as HTMLInputElement).value + // ) + // ); + // } + // } + // if (languagePick().length > 0) { + // document.getElementById("isValid")?.classList.remove("hidden"); + // } else if (languagePick().length === 0) { + // document.getElementById("isValid")?.classList.add("hidden"); + // } + // console.log(languagePick()); + // } //TODO: Style improvement - when posts section is opened in mobile view, it takes up full screen width some margin might be nice not sure but this might be due to current card styling //TODO: Style improvement - when boxes are collapsed in mobile view they are narrower than when they are expanded might be nice to keep it the same size return (
+

@@ -759,19 +761,10 @@ export const ProviderProfileView: Component = () => {
{/* Creates a list of checkboxes that drop down to multiple select */}
-
languageCheckboxes()} > - {/* */}

{

-
-
*/} + {/* +
*/}

@@ -1385,21 +1378,11 @@ export const ProviderProfileView: Component = () => {
{/* Creates a list of checkboxes that drop down to multiple select */} -
+ {/*
languageCheckboxes()} > - {/* */} -

{ const [phone, setPhone] = createSignal(""); const [firstName, setFirstName] = createSignal(""); const [lastName, setLastName] = createSignal(""); + const [email, setEmail] = createSignal(""); const [providerName, setProviderName] = createSignal(""); const [languages, setLanguages] = createSignal>(); @@ -67,24 +98,13 @@ export const ProviderRegistration: Component = () => { setFirstName(profile[0].first_name); setLastName(profile[0].last_name); setProviderName(firstName() + " " + lastName()); + setEmail(profile[0].email); } } catch (error) { console.log("Other error: " + error); } - //Will create a dropdown of all the languages in the database - try { - const { data, error } = await supabase.from("language").select("*"); - if (error) { - console.log("supabase error: " + error.message); - } else if (data!) { - setLanguages(data); - } - } catch (error) { - console.log("Language error: " + error); - } - - //Will create a dropdown of all the countries in the database (Currently only Costa Rica) + //Will create a dropdown of all the countries in the database (Currently only United States) try { const { data: countries, error } = await supabase .from("country") @@ -101,209 +121,21 @@ export const ProviderRegistration: Component = () => { console.log("Other error: " + error); } - //Will create a list of Major Municipalities based on the selected country try { - const { data: majorMunicipality, error: errorMajorMunicipality } = - await supabase.from("major_municipality").select("*"); - if (errorMajorMunicipality) { - console.log("supabase error: " + errorMajorMunicipality.message); + const { data: majorMunicipality, error: errorMajorMunicipality } = await supabase + .from("major_municipality") + .select("*"); + if (error) { + console.log("supabase error: " + error.message); } else { - document.getElementById("country")?.addEventListener("change", () => { - let municipalitySelect = document.getElementById( - "MajorMunicipality" - ) as HTMLSelectElement; - - let length = municipalitySelect?.length; - - for (let i = length - 1; i > -1; i--) { - if (municipalitySelect.options[i].value !== "") { - municipalitySelect.remove(i); - } - } - let filteredMunicipality = majorMunicipality.filter( - (municipality) => - municipality.country == - (document.getElementById("country") as HTMLSelectElement)?.value - ); - filteredMunicipality.forEach((municipality) => { - let municipalityOption = new Option( - municipality.major_municipality, - municipality.id - ); - document - .getElementById("MajorMunicipality") - ?.append(municipalityOption); - }); + majorMunicipality?.forEach((state) => { + let muniOption = new Option(state.major_municipality, state.id); + document.getElementById("MajorMunicipality")?.append(muniOption); }); } } catch (error) { console.log("Other error: " + error); } - - //Old code for minor and governing - //Creates drop down options for Minor Municipality based on selected Major Municipality - // try { - // const { data: minorMunicipality, error: errorMinorMunicipality } = - // await supabase.from("minor_municipality").select("*"); - // if (errorMinorMunicipality) { - // console.log("supabase error: " + errorMinorMunicipality.message); - // } else { - // document - // .getElementById("MajorMunicipality") - // ?.addEventListener("change", () => { - // let municipalitySelect = document.getElementById( - // "MinorMunicipality" - // ) as HTMLSelectElement; - - // let length = municipalitySelect?.length; - // let length = municipalitySelect?.length; - - // for (let i = length - 1; i > -1; i--) { - // if (municipalitySelect.options[i].value !== "") { - // municipalitySelect.remove(i); - // } - // } - // for (let i = length - 1; i > -1; i--) { - // if (municipalitySelect.options[i].value !== "") { - // municipalitySelect.remove(i); - // } - // } - - // let filteredMunicipality = minorMunicipality.filter( - // (municipality) => - // municipality.major_municipality == - // ( - // document.getElementById( - // "MajorMunicipality" - // ) as HTMLSelectElement - // )?.value - // ); - // filteredMunicipality.forEach((municipality) => { - // let municipalityOption = new Option( - // municipality.minor_municipality, - // municipality.id - // ); - // document - // .getElementById("MinorMunicipality") - // ?.append(municipalityOption); - // }); - // }); - // } - // } catch (error) { - // console.log("Other error: " + error); - // } - // let filteredMunicipality = minorMunicipality.filter( - // (municipality) => - // municipality.major_municipality == - // ( - // document.getElementById( - // "MajorMunicipality" - // ) as HTMLSelectElement - // )?.value - // ); - // filteredMunicipality.forEach((municipality) => { - // let municipalityOption = new Option( - // municipality.minor_municipality, - // municipality.id - // ); - // document - // .getElementById("MinorMunicipality") - // ?.append(municipalityOption); - // }); - // }); - // } - // } catch (error) { - // console.log("Other error: " + error); - // } - - // //Creates filtered drop down options for Governing District base on selected Minor Municipality - // try { - // const { data: governingDistrict, error: errorGoverningDistrict } = - // await supabase.from("governing_district").select("*"); - // if (errorGoverningDistrict) { - // console.log("supabase error: " + errorGoverningDistrict.message); - // } else { - // document - // .getElementById("MinorMunicipality") - // ?.addEventListener("change", () => { - // let districtSelect = document.getElementById( - // "GoverningDistrict" - // ) as HTMLSelectElement; - // //Creates filtered drop down options for Governing District base on selected Minor Municipality - // try { - // const { data: governingDistrict, error: errorGoverningDistrict } = - // await supabase.from("governing_district").select("*"); - // if (errorGoverningDistrict) { - // console.log("supabase error: " + errorGoverningDistrict.message); - // } else { - // document - // .getElementById("MinorMunicipality") - // ?.addEventListener("change", () => { - // let districtSelect = document.getElementById( - // "GoverningDistrict" - // ) as HTMLSelectElement; - - // let length = districtSelect?.length; - // let length = districtSelect?.length; - - // for (let i = length - 1; i > -1; i--) { - // if (districtSelect.options[i].value !== "") { - // districtSelect.remove(i); - // } - // } - // for (let i = length - 1; i > -1; i--) { - // if (districtSelect.options[i].value !== "") { - // districtSelect.remove(i); - // } - // } - - // let filteredDistrict = governingDistrict.filter( - // (district) => - // district.minor_municipality == - // ( - // document.getElementById( - // "MinorMunicipality" - // ) as HTMLSelectElement - // )?.value - // ); - // filteredDistrict.forEach((district) => { - // let districtOption = new Option( - // district.governing_district, - // district.id - // ); - // document - // .getElementById("GoverningDistrict") - // ?.append(districtOption); - // }); - // }); - // } - // } catch (error) { - // console.log("Other error: " + error); - // } - // let filteredDistrict = governingDistrict.filter( - // (district) => - // district.minor_municipality == - // ( - // document.getElementById( - // "MinorMunicipality" - // ) as HTMLSelectElement - // )?.value - // ); - // filteredDistrict.forEach((district) => { - // let districtOption = new Option( - // district.governing_district, - // district.id - // ); - // document - // .getElementById("GoverningDistrict") - // ?.append(districtOption); - // }); - // }); - // } - // } catch (error) { - // console.log("Other error: " + error); - // } - //If the user is not signed in then tell them to sign in and send them to the login page } else { alert(t("messages.createProviderAccount")); @@ -321,7 +153,6 @@ export const ProviderRegistration: Component = () => { //Must send the access_token and refresh_token to the APIRoute because the server can't see the local session function submit(e: SubmitEvent) { e.preventDefault(); - console.log(languages()); const formData = new FormData(e.target as HTMLFormElement); @@ -333,8 +164,11 @@ export const ProviderRegistration: Component = () => { formData.append("Phone", phone()); formData.append("access_token", session()?.access_token!); formData.append("refresh_token", session()?.refresh_token!); + formData.append("email", email()); formData.append("lang", lang); formData.append("languageArray", JSON.stringify(languagePick())); + //Remove when more countries are added + formData.set("country", "1"); // formData.append("language", languageS()); if (imageUrl() !== null) { @@ -367,30 +201,30 @@ export const ProviderRegistration: Component = () => { } } - function setLanguageArray(e: Event) { - if ((e.target as HTMLInputElement).checked) { - setLanguagePick([ - ...languagePick(), - (e.target as HTMLInputElement).value, - ]); - } else if ((e.target as HTMLInputElement).checked === false) { - if (languagePick().includes((e.target as HTMLInputElement).value)) { - setLanguagePick( - languagePick().filter( - (value) => value !== (e.target as HTMLInputElement).value - ) - ); - } - } - if (languagePick().length > 0) { - document.getElementById("isValid")?.classList.remove("hidden"); - document.getElementById("languageToolTip")?.classList.add("hidden"); - } else if (languagePick().length === 0) { - document.getElementById("isValid")?.classList.add("hidden"); - document.getElementById("languageToolTip")?.classList.remove("hidden"); - } - console.log(languagePick()); - } + // function setLanguageArray(e: Event) { + // if ((e.target as HTMLInputElement).checked) { + // setLanguagePick([ + // ...languagePick(), + // (e.target as HTMLInputElement).value, + // ]); + // } else if ((e.target as HTMLInputElement).checked === false) { + // if (languagePick().includes((e.target as HTMLInputElement).value)) { + // setLanguagePick( + // languagePick().filter( + // (value) => value !== (e.target as HTMLInputElement).value + // ) + // ); + // } + // } + // if (languagePick().length > 0) { + // document.getElementById("isValid")?.classList.remove("hidden"); + // document.getElementById("languageToolTip")?.classList.add("hidden"); + // } else if (languagePick().length === 0) { + // document.getElementById("isValid")?.classList.add("hidden"); + // document.getElementById("languageToolTip")?.classList.remove("hidden"); + // } + // console.log(languagePick()); + // } //Actual Form that gets displayed for users to fill return ( @@ -575,22 +409,16 @@ export const ProviderRegistration: Component = () => {

-
+ {/*
+ */} + {/* Creates a list of checkboxes that drop down to multiple select */} -
+ {/*
languageCheckboxes()}> - {/* */}

-
- +
*/} +
- + {/* TODO: Un-hide by removing Show when allowing countries outside US */}
-
+
- -
- - {/*
- - - - - - - -
*/} -
diff --git a/src/components/users/provider/StripeButton.tsx b/src/components/users/provider/StripeButton.tsx new file mode 100644 index 00000000..b808c78a --- /dev/null +++ b/src/components/users/provider/StripeButton.tsx @@ -0,0 +1,113 @@ +import { AuthMode } from "@components/common/AuthMode"; +import { CreatePostsRouting } from "@components/posts/CreatePostsRouting"; +import { ClientRouting } from "@components/users/ClientRouting"; +import supabase from "@lib/supabaseClient"; +import { Show, createSignal } from "solid-js"; +import { getLangFromUrl, useTranslations } from "@i18n/utils"; +import stripe from "@lib/stripe"; +import { SITE } from "src/config"; + +const lang = getLangFromUrl(new URL(window.location.href)); +const t = useTranslations(lang); + +const { data: User, error: UserError } = await supabase.auth.getSession(); + +const { data: stripeData, error: stripeError } = await supabase + .from("sellers") + .select("stripe_connected_account_id") + .eq("user_id", User!.session!.user.id); + +if (stripeError) { + console.log("Stripe Error: " + stripeError.message); +} +if (!stripeData) { + console.log("No Stripe ID found"); +} else { + console.log(stripeData) +} + +// Improvement: This probably shouldn't be needed in the button like this the page should check that before loading the button at all. But this works for now. +if (stripeData === null ||stripeData.length === 0) { + alert(t("messages.noProvider")); + location.href = `/${lang}/provider/createaccount`; +} +const stripeId = stripeData![0].stripe_connected_account_id; + + + +const stripeAcctSetup = await stripe.accounts.retrieve(stripeId).then((res) => { + return res.charges_enabled; +}); + +export const StripeButton = () => { + const [isUser, setIsUser] = createSignal(false); + const [accountSetup, setAccountSetup] = createSignal(stripeAcctSetup); + + if (User.session === null) { + // console.log("User don't exist"); + } else { + setIsUser(User.session!.user.role === "authenticated"); + } + + async function stripeSetup() { + const accountLink = await stripe.accountLinks.create({ + account: stripeId, + refresh_url: SITE.url + "/provider/profile", + return_url: SITE.url + "/provider/profile", + type: "account_onboarding", + }); + window.open(accountLink.url, "_blank"); + } + + async function stripeLogin() { + const loginLink = await stripe.accounts.createLoginLink(stripeId); + window.open(loginLink.url, "_blank"); + } + + if (UserError) { + console.log("User Error: " + UserError.message); + } + + function renderWhenFalse() { + if (accountSetup() === false) { + return ( +
+ +
+ ); + } + } + + function renderWhenTrue() { + if (accountSetup() === true) { + return ( +
+ +
+ ); + } + } + + return ( +
+ {renderWhenFalse()} + {renderWhenTrue()} +
+ ); +}; diff --git a/src/config.ts b/src/config.ts index 3e0c178e..6baa4a80 100644 --- a/src/config.ts +++ b/src/config.ts @@ -9,7 +9,7 @@ const CONFIG = { title: "LearnGrove", description: "HomeSchool description", //NEED TO ADD NEW URL - url: "https://NEWURL.com/", + url: "https://learngrove.co", devUrl: "http://localhost:4321", //NEED TO ADD NEW URL pagesDevUrl: "https://pwa.NEWURL.pages.dev", diff --git a/src/i18n/UI/English.ts b/src/i18n/UI/English.ts index 6e5c9444..f23b03f6 100644 --- a/src/i18n/UI/English.ts +++ b/src/i18n/UI/English.ts @@ -84,7 +84,7 @@ export const English = { passwordLength: `Password must be \n - at least 6 characters long \n - contain at least one number \n - contain at least one uppercase letter \n - contain at least one lowercase letter \n - contain at least one special character: \n ! @ # $ % ^ & *`, passwordValid: 'Valid password', passwordLackRequirements: 'Password does not meet requirements', - phoneLackRequirements: 'Phone number must be 8 digits long', + phoneLackRequirements: 'Please enter a valid phone number.', phoneValid: 'Valid phone number', passwordMatch: 'Passwords do not match', passwordReset: 'Password Reset', @@ -113,6 +113,7 @@ export const English = { profileEdits: 'Profile edits will only be saved after clicking the Save Profile button!', noClient: "No Client found.", noPostsSearch: "No posts match this specific search - please try a different filter or key word", + noStripeAccount: "You must complete enrollment with Stripe before posting resources.", }, formLabels: { @@ -120,7 +121,7 @@ export const English = { serviceCategory: 'Service Category', postContent: 'Post Content', country: 'Country', - majorMunicipality: 'Major Municipality', + majorMunicipality: 'State', minorMunicipality: 'Minor Municipality', governingDistrict: 'Governing District', search: 'Search', @@ -191,7 +192,7 @@ export const English = { profileEditError: "Error updating profile", noDistrict: "District not found", noMinorMunicipality: "Minor Municipality not found", - noMajorMunicipality: "Major Municipality not found", + noMajorMunicipality: "State not found", noCountry: "Country not found", locationError: "Location not submitted", providerCreateProfileError: "Error creating provider profile", diff --git a/src/i18n/UI/French.ts b/src/i18n/UI/French.ts index 2aa8c05a..1445647f 100644 --- a/src/i18n/UI/French.ts +++ b/src/i18n/UI/French.ts @@ -84,7 +84,7 @@ export const French = { passwordLength: "Le mot de passe doit être \n - au moins 6 caractères \n - contenir au moins un chiffre \n - contient au moins une lettre majuscule \n - contenir au moins une lettre minuscule \n - ccontenir au moins un caractère spécial: \n ! @ # $ % ^ & *", passwordValid: 'Mot de passe valide', passwordLackRequirements: 'Le mot de passe ne répond pas aux exigences', - phoneLackRequirements: 'Le numéro de téléphone doit comporter 8 chiffres', + phoneLackRequirements: "S'il vous plaît entrer un numéro de téléphone valide.", phoneValid: 'Numéro de téléphone valide', passwordMatch: "Les mots de passe ne correspondent pas", passwordReset: 'Réinitialisation du mot de passe', @@ -112,6 +112,7 @@ export const French = { mustSignIn: 'Vous devez être connecté pour voir les services disponibles.', profileEdits: "Les modifications du profil ne seront enregistrées qu'après avoir cliqué sur le bouton Enregistrer le profil !", noPostsSearch: "Aucun article ne correspond à cette recherche spécifique - veuillez essayer un autre filtre ou un autre mot clé", + noStripeAccount: "Vous devez terminer votre inscription auprès de Stripe avant de publier des ressources.", }, formLabels: { diff --git a/src/i18n/UI/Spanish.ts b/src/i18n/UI/Spanish.ts index 28e3a5e1..f23668f9 100644 --- a/src/i18n/UI/Spanish.ts +++ b/src/i18n/UI/Spanish.ts @@ -84,7 +84,7 @@ export const Spanish = { passwordLength: 'La contraseña debe ser \n - al menos 6 caracteres de largo \n - contener al menos un número \n - contener una letra mayúscula \n - contener 1 letra minúscula \n - contener al menos carácter especial: \n ! @ # $ % ^ & *', passwordValid: 'Contraseña valida', passwordLackRequirements: 'Contraseña no cumple con los requisitos', - phoneLackRequirements: 'El número de teléfono tiene que tener 8 digitos', + phoneLackRequirements: 'Por favor ingrese un número de teléfono válido.', phoneValid: 'Número de teléfono válido', passwordMatch: 'Las contraseñas no coinciden', passwordReset: 'Restablecimiento de contraseña', @@ -114,6 +114,7 @@ export const Spanish = { profileEdits: '¡Las ediciones del perfil solo se guardarán después de hacer clic en el botón Guardar perfil!', noClient: "No se encontró ningún cliente.", noPostsSearch: "Ninguna publicación coincide con esta búsqueda específica - pruebe con un filtro o palabra clave diferente", + noStripeAccount: "Debes completar la inscripción en Stripe antes de publicar recursos.", }, formLabels: { diff --git a/src/i18n/uiType.ts b/src/i18n/uiType.ts index 07a1be62..2c92be08 100644 --- a/src/i18n/uiType.ts +++ b/src/i18n/uiType.ts @@ -113,6 +113,7 @@ export interface uiObject { profileEdits: string, noClient: string, noPostsSearch: string, + noStripeAccount: string, }, formLabels: { diff --git a/src/lib/stripeServer.tsx b/src/lib/stripeServer.tsx new file mode 100644 index 00000000..5401ffeb --- /dev/null +++ b/src/lib/stripeServer.tsx @@ -0,0 +1,17 @@ +import Stripe from "stripe" + +const stripeKey = import.meta.env.PUBLIC_VITE_STRIPE_PRIVATE_KEY +let stripe = null; + +try { + stripe = new Stripe(stripeKey); + if (stripe === null) { + console.log("Stripe is null"); + } +} catch (error) { + if(error instanceof Error){ + console.error(error.message); + } +} + +export default stripe!; \ No newline at end of file diff --git a/src/pages/api/providerProfileSubmit.ts b/src/pages/api/providerProfileSubmit.ts index 6dcdc0f6..5c14d12c 100644 --- a/src/pages/api/providerProfileSubmit.ts +++ b/src/pages/api/providerProfileSubmit.ts @@ -25,23 +25,17 @@ export const POST: APIRoute = async ({ request, redirect }) => { const phone = formData.get("Phone"); const country = formData.get("country"); const majorMunicipality = formData.get("MajorMunicipality"); - // const minorMunicipality = formData.get("MinorMunicipality"); - // const governingDistrict = formData.get("GoverningDistrict"); - const postalArea = formData.get("PostalArea"); const imageUrl = formData.get("image_url") ? formData.get("image_url") : null; - const language = JSON.parse(formData.get("languageArray")! as string); console.log("imageURL: " + imageUrl); - console.log("language: " + language); - console.log(language?.length); // Validate the formData makes sure none of the fields are blank. Could probably do more than this like check for invalid phone numbers, blank strings, unselected location info etc. if ( !phone || !country || - // !majorMunicipality || + !majorMunicipality // !minorMunicipality || // !governingDistrict || - language?.length === 0 + // language?.length === 0 ) { return new Response( JSON.stringify({ @@ -112,46 +106,20 @@ export const POST: APIRoute = async ({ request, redirect }) => { /*Each of these retrieves the appropriate id from the database for the area level (governing district, minor municipality, major municipality, country) in order to make a proper submission to the location table */ - // const { data: districtId, error: districtError } = await supabase - // .from("governing_district") - // .select("id") - // .eq("id", governingDistrict); - // if (districtError) { - // return new Response( - // JSON.stringify({ - // message: (t("apiErrors.noDistrict")), - // }), - // { status: 500 } - // ); - // } - // - // const { data: minorMunicipalityId, error: minorMunicipalityError } = - // await supabase - // .from("minor_municipality") - // .select("id") - // .eq("id", minorMunicipality); - // if (minorMunicipalityError) { - // return new Response( - // JSON.stringify({ - // message: (t("apiErrors.noMinorMunicipality")), - // }), - // { status: 500 } - // ); - // } - - // const { data: majorMunicipalityId, error: majorMunicipalityError } = - // await supabase - // .from("major_municipality") - // .select("id") - // .eq("id", majorMunicipality); - // if (majorMunicipalityError) { - // return new Response( - // JSON.stringify({ - // message: t("apiErrors.noMajorMunicipality"), - // }), - // { status: 500 }, - // ); - // } + + const { data: majorMunicipalityId, error: majorMunicipalityError } = + await supabase + .from("major_municipality") + .select("id") + .eq("id", majorMunicipality); + if (majorMunicipalityError) { + return new Response( + JSON.stringify({ + message: t("apiErrors.noMajorMunicipality"), + }), + { status: 500 }, + ); + } const { data: countryId, error: countryError } = await supabase .from("country") @@ -168,9 +136,7 @@ export const POST: APIRoute = async ({ request, redirect }) => { //Build our submission to the location table keys need to match the field in the database you are trying to fill. let locationSubmission = { - // minor_municipality: minorMunicipalityId[0].id, - // major_municipality: majorMunicipalityId[0].id, - // governing_district: districtId[0].id, + major_municipality: majorMunicipalityId[0].id, country: countryId[0].id, user_id: user.id, }; @@ -196,8 +162,7 @@ export const POST: APIRoute = async ({ request, redirect }) => { seller_phone: phone, location: location[0].id, user_id: user.id, - image_url: imageUrl, - language_spoken: language, + image_url: imageUrl }; //submit to the providers table and select it back @@ -228,8 +193,7 @@ export const POST: APIRoute = async ({ request, redirect }) => { // If everything works send a success response return new Response( JSON.stringify({ - message: t("apiErrors.success"), - redirect: "/provider/profile", + // message: t("apiErrors.success"), }), { status: 200 }, ); diff --git a/src/pages/api/updateAccountStripe.ts b/src/pages/api/updateAccountStripe.ts new file mode 100644 index 00000000..5671e8c3 --- /dev/null +++ b/src/pages/api/updateAccountStripe.ts @@ -0,0 +1,135 @@ +import supabase from "../../lib/supabaseClientServer"; +import stripe from "../../lib/stripe"; +import type { APIRoute } from "astro"; +import type { APIContext } from "astro"; +import { useTranslations } from "@i18n/utils"; +import { SITE } from "../../config"; + +export const POST: APIRoute = async ({ request, redirect }) => { + const formData = await request.formData(); + + for (let pair of formData.entries()) { + console.log(pair[0] + ", " + pair[1]); + } + + //Set internationalization values + const lang = formData.get("lang"); + //@ts-ignore + const t = useTranslations(lang); + + const stripeAccountId = formData.get("account_id"); + const access_token = formData.get("access_token"); + const refresh_token = formData.get("refresh_token"); + + // Validate the formData - you'll probably want to do more than this + if (!stripeAccountId) { + return new Response( + JSON.stringify({ + message: t("apiErrors.missingFields"), + }), + { status: 400 } + ); + } + + async function getAccountLink() { + if (stripeAccountId === null) { + return new Response( + JSON.stringify({ + message: t("apiErrors.missingFields"), + }), + { status: 500 } + ); + } else { + const accountLink = await stripe.accountLinks.create({ + account: stripeAccountId?.toString()!, + refresh_url: SITE.url + "/provider/profile", + return_url: SITE.url + "/provider/profile", + type: "account_onboarding", + }); + + if (!accountLink) { + return new Response( + JSON.stringify({ + //TODO: Change this error to be more specific like "error creating account link" + message: t("apiErrors.providerCreateProfileError"), + }), + { status: 500 } + ); + } + + return accountLink; + } + } + + const { data: sessionData, error: sessionError } = + await supabase.auth.setSession({ + refresh_token: refresh_token!.toString(), + access_token: access_token!.toString(), + }); + if (sessionError) { + return new Response( + JSON.stringify({ + message: t("apiErrors.noSession"), + }), + { status: 500 } + ); + } + + // console.log(sessionData) + + if (!sessionData?.session) { + return new Response( + JSON.stringify({ + message: t("apiErrors.noSession"), + }), + { status: 500 } + ); + } + + const user = sessionData?.session.user; + + if (!user) { + return new Response( + JSON.stringify({ + message: t("apiErrors.noUser"), + }), + { status: 500 } + ); + } + + const { error, data } = await supabase + .from("sellers") + .update({ stripe_connected_account_id: stripeAccountId }) + .eq("user_id", user.id) + .select(); + + if (error) { + console.log(error); + return new Response( + JSON.stringify({ + message: t("apiErrors.providerCreateProfileError"), + }), + { status: 500 } + ); + } else if (!data) { + return new Response( + JSON.stringify({ + message: t("apiErrors.noProfileData"), + }), + { status: 500 } + ); + } else { + console.log("Post Data: " + JSON.stringify(data)); + } + + const accountLink = await getAccountLink(); + + // Do something with the formData, then return a success response + return new Response( + JSON.stringify({ + message: t("apiErrors.success"), + redirect: accountLink.url, + }), + { status: 200 } + ); +}; diff --git a/supabase/migrations/20240313143103_addStripeAccount.sql b/supabase/migrations/20240313143103_addStripeAccount.sql new file mode 100644 index 00000000..f8394a63 --- /dev/null +++ b/supabase/migrations/20240313143103_addStripeAccount.sql @@ -0,0 +1,23 @@ +drop view if exists "public"."sellerview"; + +alter table "public"."sellers" alter column "language_spoken" drop not null; + +create or replace view "public"."sellerview" as SELECT sellers.user_id, + sellers.created_at, + sellers.seller_name, + sellers.seller_phone, + sellers.image_url, + sellers.seller_id, + locationview.major_municipality, + profiles.first_name, + profiles.last_name, + profiles.email + FROM ((sellers + LEFT JOIN profiles ON ((sellers.user_id = profiles.user_id))) + LEFT JOIN locationview ON ((sellers.location = locationview.id))); + +alter table "public"."sellers" add column "stripe_connected_account_id" text; + +CREATE UNIQUE INDEX sellers_stripe_connected_account_id_key ON public.sellers USING btree (stripe_connected_account_id); + +alter table "public"."sellers" add constraint "sellers_stripe_connected_account_id_key" UNIQUE using index "sellers_stripe_connected_account_id_key"; diff --git a/tsconfig.json b/tsconfig.json index 06c788c0..f17ff3c1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,6 +11,7 @@ "@i18n/*" : ["src/i18n/*"], "@utils/*" : ["src/utils/*"], "@assets/*" : ["src/assets/*"], + "@lib/*" : ["src/lib/*"] }, "types": ["vite-plugin-pwa/client"], }