diff --git a/src/components/dashboard/ContentForm.tsx b/src/components/dashboard/ContentForm.tsx
index 303c1c8..68ebc58 100644
--- a/src/components/dashboard/ContentForm.tsx
+++ b/src/components/dashboard/ContentForm.tsx
@@ -1,13 +1,16 @@
import "@fontsource/inter";
import React, { useEffect, useRef, useState } from "react";
-import { Button, Col, Container, Form, Row } from "react-bootstrap";
+import { Button, Col, Container, Dropdown, Form, Row } from "react-bootstrap";
// import grabberIcon from "../../assets/svg/grabber.svg";
import { ReactComponent as GrabberIcon } from "../../assets/svg/grabber.svg";
import { ReactComponent as PencilIcon } from "../../assets/svg/pencil.svg";
import { ReactComponent as CheckmarkIcon } from "../../assets/svg/checkmark.svg";
import styles from "./ContentForm.module.css";
+import ChartComponentForm from "components/subcomponents/chartcomponents/ChartComponentForm";
+import Collapsible from "components/collapsible";
+import ProviderGallery from "./ProviderGallery";
const EditableText = ({ text, setText, isEditing, setIsEditing }) => {
const inputRef = useRef(null);
@@ -97,8 +100,9 @@ const SectionCard = ({
isEditing,
setIsEditing,
}) => {
+ const [components, setComponents] = useState([]);
return (
-
+
+ {components.map((v, i) =>
+
+ {v}
+
+ )}
- {index}
+
+
+ + Add Filter
+
+
+
+
+ setComponents([...components,
+
+
+
+ ])}>Chart
+
+ setComponents([...components,
+
+
+
+ ])}>Gallery
+
+
);
@@ -179,9 +229,8 @@ const SectionButton = ({
maxWidth: "12px",
borderTopLeftRadius: "8px",
borderBottomLeftRadius: "8px",
- backgroundColor: `${
- isSelected ? "#226DFF" : "transparent"
- }`,
+ backgroundColor: `${isSelected ? "#226DFF" : "transparent"
+ }`,
}}
>
{
style={{
backgroundColor: "#E3E9F5",
padding: "16px 16px 28px 16px",
+ width: "calc(100% - 264px)"
}}
>
{selectedSection === null ? null : (
diff --git a/src/components/dashboard/ProviderGallery.tsx b/src/components/dashboard/ProviderGallery.tsx
new file mode 100644
index 0000000..a444f20
--- /dev/null
+++ b/src/components/dashboard/ProviderGallery.tsx
@@ -0,0 +1,97 @@
+import React, { useState, useEffect } from "react";
+import ProviderGallerySlide from "./ProviderGallerySlide";
+import { storage } from "../../store";
+
+interface GallerySlide {
+ title: string;
+ description: string;
+ imgLink: string;
+}
+
+export default function ProviderGallery({
+ slidesArray = [],
+}: {
+ slidesArray?: GallerySlide[];
+}) {
+ const [slides, setSlides] = useState(slidesArray);
+
+ const defaultSlide: GallerySlide = {
+ title: "",
+ description: "",
+ imgLink: "",
+ };
+
+ useEffect(() => {
+ if (!slides || slides.length === 0) {
+ setSlides([{ ...defaultSlide }]);
+ }
+ }, [slides]);
+
+ const handleSlideDataChange = (
+ index: number,
+ field: keyof GallerySlide,
+ e: React.ChangeEvent
+ ) => {
+ const newSlides = slides.map((slide, i) =>
+ i === index ? { ...slide, [field]: e.target.value } : slide
+ );
+ setSlides(newSlides);
+ };
+
+ const handleDelete = (index: number) => {
+ if (slides.length > 1) {
+ const newSlides = slides.filter((_, i) => i !== index);
+ setSlides(newSlides);
+ }
+ };
+
+ const handleAdd = (index: number) => {
+ const newSlides = [...slides];
+ const newSlide = { ...defaultSlide };
+
+ if (index === newSlides.length - 1) {
+ newSlides.push(newSlide);
+ } else {
+ newSlides.splice(index + 1, 0, newSlide);
+ }
+ setSlides(newSlides);
+ };
+
+ const handleUpload = async (file, index: number) => {
+ const filename = file.name;
+ const fileRef = storage.ref("images").child(filename);
+
+ await fileRef.put(file);
+ const url = await fileRef.getDownloadURL();
+
+ const newSlides = slides.map((slide, i) =>
+ i === index ? { ...slide, imgLink: url } : slide
+ );
+ setSlides(newSlides);
+ };
+
+ const renderSlides = () => {
+ return slides.map((slide, i) => (
+
+ ));
+ };
+
+ return (
+
+ {renderSlides()}
+ {/*TO BE DELETED */}
+
+
Current Data:
+
{JSON.stringify(slides, null, 2)}
+
+
+ );
+}
diff --git a/src/components/dashboard/ProviderGalleryCarousel.tsx b/src/components/dashboard/ProviderGalleryCarousel.tsx
new file mode 100644
index 0000000..dd0f1f5
--- /dev/null
+++ b/src/components/dashboard/ProviderGalleryCarousel.tsx
@@ -0,0 +1,181 @@
+import React, { useState } from "react";
+
+interface GallerySlide {
+ title: string;
+ description: string;
+ imgLink: string;
+}
+
+export default function ProviderGalleryCarousel({
+ slidesArray,
+}: {
+ slidesArray: GallerySlide[];
+}) {
+ const [currentIndex, setCurrentIndex] = useState(0);
+
+ const goToPrevious = () => {
+ setCurrentIndex((prevIndex) =>
+ prevIndex === 0 ? slidesArray.length - 1 : prevIndex - 1
+ );
+ };
+
+ const goToNext = () => {
+ setCurrentIndex((prevIndex) =>
+ prevIndex === slidesArray.length - 1 ? 0 : prevIndex + 1
+ );
+ };
+
+ const isActive = (index: number) => currentIndex === index;
+
+ return (
+
+
+
+ {`<`}
+
+
+ {/* Card */}
+
+ {/*Left-side */}
+
+ {/* Card Title */}
+
+
+ {slidesArray[currentIndex].title}
+
+
+
+ {/* Card Description */}
+
+
+ {slidesArray[currentIndex].description}
+
+
+
+ {/*Right-side*/}
+
+
+
+
+
+ {`>`}
+
+
+
+ {/* bubbles */}
+
+ {slidesArray.map((_, index) => (
+
+ ))}
+
+
+ );
+}
diff --git a/src/components/dashboard/ProviderGallerySlide.tsx b/src/components/dashboard/ProviderGallerySlide.tsx
new file mode 100644
index 0000000..a79440a
--- /dev/null
+++ b/src/components/dashboard/ProviderGallerySlide.tsx
@@ -0,0 +1,176 @@
+import React, { useState } from "react";
+import Form from "react-bootstrap/Form";
+import { Button } from "react-bootstrap";
+import Dropzone from "react-dropzone";
+
+export default function ProviderGallerySlide({
+ title,
+ description,
+ imgLink, // Opens use of imgLink in slide for editing maybe?
+ index,
+ handleSlideDataChange,
+ handleDelete,
+ handleAdd,
+ handleUpload,
+}) {
+ return (
+
+
{`Slide ${index + 1}`}
+
+
+ Title *
+
+
+ handleSlideDataChange(index, "title", e)
+ }
+ style={{ borderColor: "#D9D9D9" }}
+ required
+ />
+
+
+ Description
+
+ handleSlideDataChange(index, "description", e)
+ }
+ style={{ borderColor: "#D9D9D9" }}
+ />
+
+
+ Upload file
+
+
+
+
+
+ handleDelete(index)}
+ style={{
+ all: "unset",
+ cursor: "pointer",
+ color: "#4F4F4F",
+ }}
+ >
+ Delete
+
+
+
handleAdd(index)}
+ style={{
+ backgroundColor: "white",
+ color: "#226DFF",
+ fontWeight: "500",
+ letterSpacing: "-0.176px",
+ lineHeight: "150%",
+ fontSize: "1rem",
+ padding: "8px",
+ border: "border: 1px solid #226DFF",
+ width: "fit-content",
+ }}
+ >
+ + Add slide
+
+
+
+ );
+}
+
+const ImageModal = ({ handleSuccess, index }) => {
+ const [uploaded, setUploaded] = useState(false);
+ const [image, setImage] = useState(null);
+
+ const handleDrop = (img) => {
+ setImage(img[0]);
+ setUploaded(true);
+ };
+
+ return (
+
+ {!uploaded && (
+
+ {({ getRootProps, getInputProps }) => (
+
+
+
+ Drop your image here, or{" "}
+ browse
+
+
Supports JPG, JPEG2000, PNG
+
+ )}
+
+ )}
+ {uploaded && (
+
+
+
+
+
setUploaded(false)}
+ >
+ Cancel
+
+
{
+ handleSuccess(image, index);
+ setUploaded(false);
+ }}
+ >
+ Save
+
+
+ )}
+
+ );
+};
diff --git a/src/components/dashboard/RowForm.tsx b/src/components/dashboard/RowForm.tsx
index c279b47..5a970ec 100644
--- a/src/components/dashboard/RowForm.tsx
+++ b/src/components/dashboard/RowForm.tsx
@@ -19,6 +19,33 @@ import Button from "react-bootstrap/Button";
import ActionForm from "./ActionForm";
import ContentForm from "./ContentForm";
+const galleryData = [
+ {
+ title: "testVal1",
+ description: "testing testing",
+ imgLink:
+ "https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/45ed8ecf-0bb2-4e34-8fcf-624db47c43c8/Golden+Retrievers+dans+pet+care.jpeg",
+ },
+ {
+ title: "testVal2",
+ description: "testing testing",
+ imgLink:
+ "https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/45ed8ecf-0bb2-4e34-8fcf-624db47c43c8/Golden+Retrievers+dans+pet+care.jpeg",
+ },
+ {
+ title: "testVal3",
+ description: "testing testing",
+ imgLink:
+ "https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/45ed8ecf-0bb2-4e34-8fcf-624db47c43c8/Golden+Retrievers+dans+pet+care.jpeg",
+ },
+ {
+ title: "testVal4",
+ description: "testing testing",
+ imgLink:
+ "https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/45ed8ecf-0bb2-4e34-8fcf-624db47c43c8/Golden+Retrievers+dans+pet+care.jpeg",
+ },
+];
+
function validURL(str) {
const pattern = new RegExp(
"^(https?:\\/\\/)?" + // protocol
@@ -27,7 +54,7 @@ function validURL(str) {
"(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + // port and path
"(\\?[;&a-z\\d%_.~+=-]*)?" + // query string
"(\\#[-a-z\\d_]*)?$",
- "i",
+ "i"
); // fragment locator
return !!pattern.test(str);
}
@@ -248,9 +275,9 @@ const RowForm = (props) => {
style={{
color: isValidNumberForRegion(
parseIncompletePhoneNumber(
- item.phoneNum[0],
+ item.phoneNum[0]
),
- "US",
+ "US"
)
? "green"
: "red",
@@ -258,9 +285,9 @@ const RowForm = (props) => {
>
{isValidNumberForRegion(
parseIncompletePhoneNumber(
- item.phoneNum[0],
+ item.phoneNum[0]
),
- "US",
+ "US"
)
? "Valid number"
: "Invalid number"}
@@ -387,7 +414,7 @@ const RowForm = (props) => {
}}
/>
- ),
+ )
)}
>
);
@@ -411,7 +438,7 @@ const RowForm = (props) => {
}}
/>
- ),
+ )
)}
>
);
@@ -437,7 +464,7 @@ const RowForm = (props) => {
}}
/>
- ),
+ )
)}
>
);
diff --git a/src/components/subcomponents/ProviderInfo.tsx b/src/components/subcomponents/ProviderInfo.tsx
index 0f86a87..d9f2479 100644
--- a/src/components/subcomponents/ProviderInfo.tsx
+++ b/src/components/subcomponents/ProviderInfo.tsx
@@ -11,6 +11,64 @@ import ReadMoreAndLess from "react-read-more-less";
import LazyLoad from "react-lazy-load";
import { GOOGLE_API_KEY } from "../../config/keys";
import Linkify from "react-linkify";
+import ProviderGalleryCarousel from "components/dashboard/ProviderGalleryCarousel";
+import Collapsible from "components/collapsible";
+
+{
+ /*TO BE DELETED */
+}
+const galleryData = [
+ {
+ title: "Urban Tree Fundraiser",
+ description:
+ "Last Friday, we gathered for food, fun, and giving back at Urban Tree cidery. All proceeds from the evening went to our Bereavement fund. Everyone remembered to bring a sweater because the back deck got cold. We enjoyed drinks, games, and more!",
+ imgLink:
+ "https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/45ed8ecf-0bb2-4e34-8fcf-624db47c43c8/Golden+Retrievers+dans+pet+care.jpeg",
+ },
+ {
+ title: "testVal2",
+ description: "testing testing",
+ imgLink:
+ "https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/45ed8ecf-0bb2-4e34-8fcf-624db47c43c8/Golden+Retrievers+dans+pet+care.jpeg",
+ },
+ {
+ title: "testVal3",
+ description: "testing testing",
+ imgLink:
+ "https://static.vecteezy.com/system/resources/thumbnails/005/857/332/small_2x/funny-portrait-of-cute-corgi-dog-outdoors-free-photo.jpg",
+ },
+ {
+ title: "testVal4",
+ description: "testing testing",
+ imgLink:
+ "https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/45ed8ecf-0bb2-4e34-8fcf-624db47c43c8/Golden+Retrievers+dans+pet+care.jpeg",
+ },
+ {
+ title: "testVal1",
+ description: "testing testing",
+ imgLink:
+ "https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/45ed8ecf-0bb2-4e34-8fcf-624db47c43c8/Golden+Retrievers+dans+pet+care.jpeg",
+ },
+ {
+ title: "testVal2",
+ description: "testing testing",
+ imgLink:
+ "https://static.vecteezy.com/system/resources/thumbnails/005/857/332/small_2x/funny-portrait-of-cute-corgi-dog-outdoors-free-photo.jpg",
+ },
+ {
+ title: "testVal3",
+ description: "testing testing",
+ imgLink:
+ "https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/45ed8ecf-0bb2-4e34-8fcf-624db47c43c8/Golden+Retrievers+dans+pet+care.jpeg",
+ },
+ {
+ title: "testVal4",
+ description: "testing testing",
+ imgLink:
+ "https://images.squarespace-cdn.com/content/v1/54822a56e4b0b30bd821480c/45ed8ecf-0bb2-4e34-8fcf-624db47c43c8/Golden+Retrievers+dans+pet+care.jpeg",
+ },
+];
+
const ProviderInfo = (props) => {
const [image, setImage] = useState("bog");
@@ -23,7 +81,7 @@ const ProviderInfo = (props) => {
try {
const res2 = await fetch(
`https://maps.googleapis.com/maps/api/staticmap?center=${props.item.latitude},${props.item.longitude}&zoom=16&scale=2&size=335x250&maptype=roadmap&key=${GOOGLE_API_KEY}&format=png&visual_refresh=true` +
- `&markers=${props.item.latitude},${props.item.longitude}`,
+ `&markers=${props.item.latitude},${props.item.longitude}`,
);
setStreetView(res2.url);
setImage(props.item.imageURL);
@@ -101,7 +159,7 @@ const ProviderInfo = (props) => {
index ===
props.item.address.toString().split(",")
.length -
- 1
+ 1
) {
return (
@@ -163,6 +221,14 @@ const ProviderInfo = (props) => {
+
+
+
+ {/*TO BE DELETED */}
+
+
+
+
{categoriesToUse
.filter(
@@ -181,7 +247,7 @@ const ProviderInfo = (props) => {
if (
index !==
props.item[category.id].length -
- 1
+ 1
) {
return (
@@ -230,9 +296,9 @@ function calculateHours(props) {
!props.item.hours[days[i]] ||
!props.item.hours[days[i - 1]] ||
props.item.hours[days[i]][0] !==
- props.item.hours[days[i - 1]][0] ||
+ props.item.hours[days[i - 1]][0] ||
props.item.hours[days[i]][1] !==
- props.item.hours[days[i - 1]][1]
+ props.item.hours[days[i - 1]][1]
) {
startandFinish.push(i - 1);
startandFinish.push(i);
@@ -267,13 +333,13 @@ function calculateHours(props) {
{props.item.hours[days[startandFinish[i]]]
? props.item.hours[days[startandFinish[i]]].map(
- (time, index) =>
- formatTime(
- props.item.hours[days[startandFinish[i]]],
- time,
- index,
- ),
- )
+ (time, index) =>
+ formatTime(
+ props.item.hours[days[startandFinish[i]]],
+ time,
+ index,
+ ),
+ )
: "CLOSED"}
,
);
diff --git a/src/components/subcomponents/chartcomponents/ChartComponentForm.tsx b/src/components/subcomponents/chartcomponents/ChartComponentForm.tsx
index 344b308..0249fd3 100644
--- a/src/components/subcomponents/chartcomponents/ChartComponentForm.tsx
+++ b/src/components/subcomponents/chartcomponents/ChartComponentForm.tsx
@@ -500,7 +500,7 @@ const ChartComponentForm = () => {
return (