diff --git a/amplify/backend/api/pinesearch/schema.graphql b/amplify/backend/api/pinesearch/schema.graphql
index ae3c4ea..641845c 100644
--- a/amplify/backend/api/pinesearch/schema.graphql
+++ b/amplify/backend/api/pinesearch/schema.graphql
@@ -1,3 +1,15 @@
+type Comment {
+ author: String!
+ comment: String!
+ gpt_response: String!
+}
+
+type PostComments @model @auth(rules: [{allow: public}]) {
+ id: ID!
+ s3url: String!
+ users_comments: [Comment!]!
+}
+
type PostLikes @model @auth(rules: [{allow: public}]) {
id: ID!
s3url: String
diff --git a/public/icons/SendIcon.tsx b/public/icons/SendIcon.tsx
new file mode 100644
index 0000000..abdc57d
--- /dev/null
+++ b/public/icons/SendIcon.tsx
@@ -0,0 +1,13 @@
+export const SendIcon = () => {
+ return (
+
+ );
+};
diff --git a/src/app/blog/[slug]/Buttons.tsx b/src/app/blog/[slug]/Buttons.tsx
index e5c6f58..63856b1 100644
--- a/src/app/blog/[slug]/Buttons.tsx
+++ b/src/app/blog/[slug]/Buttons.tsx
@@ -17,7 +17,7 @@ export const Buttons = ({ slug }: Props) => {
- {/* */}
+
{/* */}
diff --git a/src/app/blog/[slug]/buttons/CommentsBtn.tsx b/src/app/blog/[slug]/buttons/CommentsBtn.tsx
index c96098c..cbe97ea 100644
--- a/src/app/blog/[slug]/buttons/CommentsBtn.tsx
+++ b/src/app/blog/[slug]/buttons/CommentsBtn.tsx
@@ -1,19 +1,20 @@
-import { useOpen } from "@/hooks/useOpen";
import { CommentIcon } from "../../../../../public/icons/CommentIcon";
-import { ChatModal } from "../chatModal/ChatModal";
export const CommentsBtn = () => {
- const { isOpen, containerRef, handleClose } = useOpen();
-
+ const scrollToComments = () => {
+ const commentsSection = document.getElementById("comments");
+ if (commentsSection) {
+ commentsSection.scrollIntoView({ behavior: "smooth" });
+ }
+ };
return (
- {isOpen && }
);
};
diff --git a/src/app/blog/[slug]/chatModal/ChatForm.tsx b/src/app/blog/[slug]/chatModal/ChatForm.tsx
deleted file mode 100644
index d1c8409..0000000
--- a/src/app/blog/[slug]/chatModal/ChatForm.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-export const ChatForm = () => {
- return (
-
- );
-};
diff --git a/src/app/blog/[slug]/chatModal/ChatModal.tsx b/src/app/blog/[slug]/chatModal/ChatModal.tsx
deleted file mode 100644
index 1ccf10a..0000000
--- a/src/app/blog/[slug]/chatModal/ChatModal.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import { CloseIcon } from "../../../../../public/icons/CloseIcon";
-import { ChatForm } from "./ChatForm";
-
-interface Props {
- containerRef: React.Ref;
- handleClose: () => void;
-}
-
-const dummyData = [
- {
- author: "saul",
- comment:
- "Lorem ipsum dolor sit amet consectetur adipisicing elit. Provident omnis, aperiam in magnam vitae nesciunt, possimus consequatur exercitationem dicta blanditiis asperiores distinctio vero accusantium voluptatibus? Provident porro architecto fugiat iste. Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt ducimus earum dolore. Minus itaque, velit omnis molestias doloremque culpa temporibus ipsum laudantium aliquam modi incidunt consectetur earum. Earum, corporis architecto."
- },
- {
- author: null,
- comment:
- "Lorem ipsum dolor sit amet consectetur adipisicing elit. Provident omnis, aperiam in magnam vitae nesciunt, possimus consequatur exercitationem dicta blanditiis asperiores distinctio vero accusantium voluptatibus? Provident porro architecto fugiat iste. Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt ducimus earum dolore. Minus, itaque, velit omnis molestias doloremque culpa temporibus ipsum laudantium aliquam modi incidunt consectetur earum. Earum, corporis architecto."
- }
-];
-
-export const ChatModal = ({ containerRef, handleClose }: Props) => {
- return (
-
-
-
-
-
-
-
- Show last 10 comments →
-
-
-
- {dummyData.map((data, i) => (
-
- {data.comment}
-
- ))}
-
-
-
-
-
-
- );
-};
-
-interface ChatItemProps {
- author: string | null;
- children: React.ReactNode;
-}
-
-const ChatItem = ({ author, children }: ChatItemProps) => {
- let createdBy = author ? author : "Pinebot";
- const firstLetter = createdBy[0].toUpperCase();
- const bg = createdBy === "Pinebot" ? "bg-blue-100" : "bg-green-100";
-
- return (
-
-
-
- {firstLetter}
-
-
{createdBy}
-
-
-
- );
-};
diff --git a/src/app/blog/[slug]/comments/CommentForm.tsx b/src/app/blog/[slug]/comments/CommentForm.tsx
new file mode 100644
index 0000000..c904816
--- /dev/null
+++ b/src/app/blog/[slug]/comments/CommentForm.tsx
@@ -0,0 +1,38 @@
+import { FormEvent, useRef, useState } from "react";
+import { useAuth } from "@/hooks/useAuth";
+import { SendIcon } from "../../../../../public/icons/SendIcon";
+
+interface Props {
+ handleAddComment: (comment: string, author: string) => Promise;
+}
+export const CommentForm = ({ handleAddComment }: Props) => {
+ const { getUser } = useAuth();
+ const user = getUser()?.attributes?.email;
+ const [commentValue, setCommentValue] = useState("");
+
+ const handleSubmit = (e: FormEvent) => {
+ e.preventDefault();
+ console.log(user);
+
+ if (!user) return;
+ if (!commentValue.trim()) return;
+
+ handleAddComment(commentValue, user);
+ setCommentValue("");
+ };
+
+ return (
+
+ );
+};
diff --git a/src/app/blog/[slug]/comments/CommentItem.tsx b/src/app/blog/[slug]/comments/CommentItem.tsx
new file mode 100644
index 0000000..551a52f
--- /dev/null
+++ b/src/app/blog/[slug]/comments/CommentItem.tsx
@@ -0,0 +1,40 @@
+interface Props {
+ author: string;
+ comment: string;
+ gpt_response: string;
+}
+
+export const ChatItem = ({ author, comment, gpt_response }: Props) => {
+ return (
+
+ );
+};
+
+interface ItemProps {
+ author: string;
+ comment: string;
+ isBot?: boolean;
+}
+
+const Item = ({ author, comment, isBot }: ItemProps) => {
+ return (
+ <>
+
+
+ {isBot ? "P" : author[0].toUpperCase()}
+
+
{isBot ? "Pinebot" : author}
+
+
+ >
+ );
+};
diff --git a/src/app/blog/[slug]/comments/Comments.tsx b/src/app/blog/[slug]/comments/Comments.tsx
new file mode 100644
index 0000000..45dae23
--- /dev/null
+++ b/src/app/blog/[slug]/comments/Comments.tsx
@@ -0,0 +1,89 @@
+"use client";
+
+import { useEffect, useState } from "react";
+import { Comment, PostComments } from "@/models";
+import { DataStore } from "aws-amplify";
+import { ChatItem } from "./CommentItem";
+import { CommentForm } from "./CommentForm";
+
+interface Props {
+ slug: string;
+}
+
+export const Comments = ({ slug }: Props) => {
+ const [totalComments, setTotalComments] = useState([]);
+ const [showTotalComments, setShowTotalComments] = useState(false);
+
+ const getComment = async () => {
+ const postComments: PostComments = (
+ await DataStore.query(PostComments, (postComments: any) => postComments.s3url.eq(slug))
+ )[0];
+
+ // if there are no comments is created --> test
+ if (!postComments?.id) {
+ await DataStore.save(
+ new PostComments({
+ s3url: slug,
+ users_comments: []
+ })
+ );
+ return;
+ }
+
+ setTotalComments(postComments.users_comments);
+ };
+
+ const updateRestComments = (postComent: PostComments): Comment[] => {
+ if (postComent.users_comments.length >= 10) return postComent.users_comments.slice(0, 9);
+
+ return postComent.users_comments;
+ };
+
+ const handleAddComment = async (comment: string, author: string) => {
+ const gptResponse = "Hi I'm Pinebot, glad you liked the post, thanks for reading us"; //await getGtp();
+
+ const currentComment = (
+ await DataStore.query(PostComments, (postLikes: any) => postLikes.s3url.eq(slug))
+ )[0]!;
+
+ const updatedPost = await DataStore.save(
+ PostComments.copyOf(currentComment, (updated) => {
+ updated.users_comments = [
+ {
+ author: author,
+ comment: comment,
+ gpt_response: gptResponse
+ },
+ ...updateRestComments(updated)
+ ];
+ })
+ );
+ setTotalComments(updatedPost.users_comments);
+ };
+
+ useEffect(() => {
+ getComment();
+ }, []);
+
+ return (
+
+ );
+};
diff --git a/src/app/blog/[slug]/page.tsx b/src/app/blog/[slug]/page.tsx
index e16608e..a92ecd5 100644
--- a/src/app/blog/[slug]/page.tsx
+++ b/src/app/blog/[slug]/page.tsx
@@ -3,6 +3,7 @@ import { SortDirection, Storage, withSSRContext } from "aws-amplify";
import { MDXRemote } from "next-mdx-remote/rsc";
import { ImageClient } from "@/components/ImageClient";
import { Buttons } from "./Buttons";
+import { Comments } from "./comments/Comments";
interface StaticParams {
slug: string;
@@ -60,8 +61,8 @@ export default async function blogPage({ params }: BlogPageParams) {
return (
mdxSource && (
-
-
+
+ >
)
);
}
diff --git a/src/models/index.d.ts b/src/models/index.d.ts
index cac4ec2..714fafe 100644
--- a/src/models/index.d.ts
+++ b/src/models/index.d.ts
@@ -4,7 +4,51 @@ import { LazyLoading, LazyLoadingDisabled } from "@aws-amplify/datastore";
+type EagerComment = {
+ readonly author: string;
+ readonly comment: string;
+ readonly gpt_response: string;
+}
+
+type LazyComment = {
+ readonly author: string;
+ readonly comment: string;
+ readonly gpt_response: string;
+}
+export declare type Comment = LazyLoading extends LazyLoadingDisabled ? EagerComment : LazyComment
+
+export declare const Comment: (new (init: ModelInit) => Comment)
+
+type EagerPostComments = {
+ readonly [__modelMeta__]: {
+ identifier: ManagedIdentifier;
+ readOnlyFields: 'createdAt' | 'updatedAt';
+ };
+ readonly id: string;
+ readonly s3url: string;
+ readonly users_comments: Comment[];
+ readonly createdAt?: string | null;
+ readonly updatedAt?: string | null;
+}
+
+type LazyPostComments = {
+ readonly [__modelMeta__]: {
+ identifier: ManagedIdentifier;
+ readOnlyFields: 'createdAt' | 'updatedAt';
+ };
+ readonly id: string;
+ readonly s3url: string;
+ readonly users_comments: Comment[];
+ readonly createdAt?: string | null;
+ readonly updatedAt?: string | null;
+}
+
+export declare type PostComments = LazyLoading extends LazyLoadingDisabled ? EagerPostComments : LazyPostComments
+
+export declare const PostComments: (new (init: ModelInit) => PostComments) & {
+ copyOf(source: PostComments, mutator: (draft: MutableModel) => MutableModel | void): PostComments;
+}
type EagerPostLikes = {
readonly [__modelMeta__]: {
diff --git a/src/models/index.js b/src/models/index.js
index 987c2fd..9e84626 100644
--- a/src/models/index.js
+++ b/src/models/index.js
@@ -4,9 +4,11 @@ import { schema } from './schema';
-const { PostLikes, Post } = initSchema(schema);
+const { PostComments, PostLikes, Post, Comment } = initSchema(schema);
export {
+ PostComments,
PostLikes,
- Post
+ Post,
+ Comment
};
\ No newline at end of file
diff --git a/src/models/schema.js b/src/models/schema.js
index 09d7e3e..4f13ffe 100644
--- a/src/models/schema.js
+++ b/src/models/schema.js
@@ -1,5 +1,74 @@
export const schema = {
"models": {
+ "PostComments": {
+ "name": "PostComments",
+ "fields": {
+ "id": {
+ "name": "id",
+ "isArray": false,
+ "type": "ID",
+ "isRequired": true,
+ "attributes": []
+ },
+ "s3url": {
+ "name": "s3url",
+ "isArray": false,
+ "type": "String",
+ "isRequired": true,
+ "attributes": []
+ },
+ "users_comments": {
+ "name": "users_comments",
+ "isArray": true,
+ "type": {
+ "nonModel": "Comment"
+ },
+ "isRequired": true,
+ "attributes": [],
+ "isArrayNullable": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "isArray": false,
+ "type": "AWSDateTime",
+ "isRequired": false,
+ "attributes": [],
+ "isReadOnly": true
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "isArray": false,
+ "type": "AWSDateTime",
+ "isRequired": false,
+ "attributes": [],
+ "isReadOnly": true
+ }
+ },
+ "syncable": true,
+ "pluralName": "PostComments",
+ "attributes": [
+ {
+ "type": "model",
+ "properties": {}
+ },
+ {
+ "type": "auth",
+ "properties": {
+ "rules": [
+ {
+ "allow": "public",
+ "operations": [
+ "create",
+ "update",
+ "delete",
+ "read"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ },
"PostLikes": {
"name": "PostLikes",
"fields": {
@@ -142,7 +211,34 @@ export const schema = {
}
},
"enums": {},
- "nonModels": {},
+ "nonModels": {
+ "Comment": {
+ "name": "Comment",
+ "fields": {
+ "author": {
+ "name": "author",
+ "isArray": false,
+ "type": "String",
+ "isRequired": true,
+ "attributes": []
+ },
+ "comment": {
+ "name": "comment",
+ "isArray": false,
+ "type": "String",
+ "isRequired": true,
+ "attributes": []
+ },
+ "gpt_response": {
+ "name": "gpt_response",
+ "isArray": false,
+ "type": "String",
+ "isRequired": true,
+ "attributes": []
+ }
+ }
+ }
+ },
"codegenVersion": "3.4.4",
- "version": "b4b3ab3d18625e891790e44a10dd6870"
+ "version": "5c9e6b2f0c2d205199ef8280bdeee070"
};
\ No newline at end of file
diff --git a/src/ui-components/PostCommentsCreateForm.d.ts b/src/ui-components/PostCommentsCreateForm.d.ts
new file mode 100644
index 0000000..135e0fe
--- /dev/null
+++ b/src/ui-components/PostCommentsCreateForm.d.ts
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * The contents of this file were generated with Amplify Studio. *
+ * Please refrain from making any modifications to this file. *
+ * Any changes to this file will be overwritten when running amplify pull. *
+ **************************************************************************/
+
+import * as React from "react";
+import { GridProps, TextAreaFieldProps, TextFieldProps } from "@aws-amplify/ui-react";
+import { EscapeHatchProps } from "@aws-amplify/ui-react/internal";
+export declare type ValidationResponse = {
+ hasError: boolean;
+ errorMessage?: string;
+};
+export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
+export declare type PostCommentsCreateFormInputValues = {
+ s3url?: string;
+ users_comments?: string[];
+};
+export declare type PostCommentsCreateFormValidationValues = {
+ s3url?: ValidationFunction;
+ users_comments?: ValidationFunction;
+};
+export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
+export declare type PostCommentsCreateFormOverridesProps = {
+ PostCommentsCreateFormGrid?: PrimitiveOverrideProps;
+ s3url?: PrimitiveOverrideProps;
+ users_comments?: PrimitiveOverrideProps;
+} & EscapeHatchProps;
+export declare type PostCommentsCreateFormProps = React.PropsWithChildren<{
+ overrides?: PostCommentsCreateFormOverridesProps | undefined | null;
+} & {
+ clearOnSuccess?: boolean;
+ onSubmit?: (fields: PostCommentsCreateFormInputValues) => PostCommentsCreateFormInputValues;
+ onSuccess?: (fields: PostCommentsCreateFormInputValues) => void;
+ onError?: (fields: PostCommentsCreateFormInputValues, errorMessage: string) => void;
+ onChange?: (fields: PostCommentsCreateFormInputValues) => PostCommentsCreateFormInputValues;
+ onValidate?: PostCommentsCreateFormValidationValues;
+} & React.CSSProperties>;
+export default function PostCommentsCreateForm(props: PostCommentsCreateFormProps): React.ReactElement;
diff --git a/src/ui-components/PostCommentsCreateForm.jsx b/src/ui-components/PostCommentsCreateForm.jsx
new file mode 100644
index 0000000..6091a18
--- /dev/null
+++ b/src/ui-components/PostCommentsCreateForm.jsx
@@ -0,0 +1,388 @@
+/***************************************************************************
+ * The contents of this file were generated with Amplify Studio. *
+ * Please refrain from making any modifications to this file. *
+ * Any changes to this file will be overwritten when running amplify pull. *
+ **************************************************************************/
+
+/* eslint-disable */
+import * as React from "react";
+import {
+ Badge,
+ Button,
+ Divider,
+ Flex,
+ Grid,
+ Icon,
+ ScrollView,
+ Text,
+ TextAreaField,
+ TextField,
+ useTheme,
+} from "@aws-amplify/ui-react";
+import { getOverrideProps } from "@aws-amplify/ui-react/internal";
+import { PostComments } from "../models";
+import { fetchByPath, validateField } from "./utils";
+import { DataStore } from "aws-amplify";
+function ArrayField({
+ items = [],
+ onChange,
+ label,
+ inputFieldRef,
+ children,
+ hasError,
+ setFieldValue,
+ currentFieldValue,
+ defaultFieldValue,
+ lengthLimit,
+ getBadgeText,
+ runValidationTasks,
+ errorMessage,
+}) {
+ const labelElement = {label};
+ const {
+ tokens: {
+ components: {
+ fieldmessages: { error: errorStyles },
+ },
+ },
+ } = useTheme();
+ const [selectedBadgeIndex, setSelectedBadgeIndex] = React.useState();
+ const [isEditing, setIsEditing] = React.useState();
+ React.useEffect(() => {
+ if (isEditing) {
+ inputFieldRef?.current?.focus();
+ }
+ }, [isEditing]);
+ const removeItem = async (removeIndex) => {
+ const newItems = items.filter((value, index) => index !== removeIndex);
+ await onChange(newItems);
+ setSelectedBadgeIndex(undefined);
+ };
+ const addItem = async () => {
+ const { hasError } = runValidationTasks();
+ if (
+ currentFieldValue !== undefined &&
+ currentFieldValue !== null &&
+ currentFieldValue !== "" &&
+ !hasError
+ ) {
+ const newItems = [...items];
+ if (selectedBadgeIndex !== undefined) {
+ newItems[selectedBadgeIndex] = currentFieldValue;
+ setSelectedBadgeIndex(undefined);
+ } else {
+ newItems.push(currentFieldValue);
+ }
+ await onChange(newItems);
+ setIsEditing(false);
+ }
+ };
+ const arraySection = (
+
+ {!!items?.length && (
+
+ {items.map((value, index) => {
+ return (
+ {
+ setSelectedBadgeIndex(index);
+ setFieldValue(items[index]);
+ setIsEditing(true);
+ }}
+ >
+ {getBadgeText ? getBadgeText(value) : value.toString()}
+ {
+ event.stopPropagation();
+ removeItem(index);
+ }}
+ />
+
+ );
+ })}
+
+ )}
+
+
+ );
+ if (lengthLimit !== undefined && items.length >= lengthLimit && !isEditing) {
+ return (
+
+ {labelElement}
+ {arraySection}
+
+ );
+ }
+ return (
+
+ {labelElement}
+ {isEditing && children}
+ {!isEditing ? (
+ <>
+
+ {errorMessage && hasError && (
+
+ {errorMessage}
+
+ )}
+ >
+ ) : (
+
+ {(currentFieldValue || isEditing) && (
+
+ )}
+
+
+ )}
+ {arraySection}
+
+ );
+}
+export default function PostCommentsCreateForm(props) {
+ const {
+ clearOnSuccess = true,
+ onSuccess,
+ onError,
+ onSubmit,
+ onValidate,
+ onChange,
+ overrides,
+ ...rest
+ } = props;
+ const initialValues = {
+ s3url: "",
+ users_comments: [],
+ };
+ const [s3url, setS3url] = React.useState(initialValues.s3url);
+ const [users_comments, setUsers_comments] = React.useState(
+ initialValues.users_comments
+ );
+ const [errors, setErrors] = React.useState({});
+ const resetStateValues = () => {
+ setS3url(initialValues.s3url);
+ setUsers_comments(initialValues.users_comments);
+ setCurrentUsers_commentsValue("");
+ setErrors({});
+ };
+ const [currentUsers_commentsValue, setCurrentUsers_commentsValue] =
+ React.useState("");
+ const users_commentsRef = React.createRef();
+ const validations = {
+ s3url: [{ type: "Required" }],
+ users_comments: [{ type: "Required" }, { type: "JSON" }],
+ };
+ const runValidationTasks = async (
+ fieldName,
+ currentValue,
+ getDisplayValue
+ ) => {
+ const value =
+ currentValue && getDisplayValue
+ ? getDisplayValue(currentValue)
+ : currentValue;
+ let validationResponse = validateField(value, validations[fieldName]);
+ const customValidator = fetchByPath(onValidate, fieldName);
+ if (customValidator) {
+ validationResponse = await customValidator(value, validationResponse);
+ }
+ setErrors((errors) => ({ ...errors, [fieldName]: validationResponse }));
+ return validationResponse;
+ };
+ return (
+ {
+ event.preventDefault();
+ let modelFields = {
+ s3url,
+ users_comments,
+ };
+ const validationResponses = await Promise.all(
+ Object.keys(validations).reduce((promises, fieldName) => {
+ if (Array.isArray(modelFields[fieldName])) {
+ promises.push(
+ ...modelFields[fieldName].map((item) =>
+ runValidationTasks(fieldName, item)
+ )
+ );
+ return promises;
+ }
+ promises.push(
+ runValidationTasks(fieldName, modelFields[fieldName])
+ );
+ return promises;
+ }, [])
+ );
+ if (validationResponses.some((r) => r.hasError)) {
+ return;
+ }
+ if (onSubmit) {
+ modelFields = onSubmit(modelFields);
+ }
+ try {
+ Object.entries(modelFields).forEach(([key, value]) => {
+ if (typeof value === "string" && value === "") {
+ modelFields[key] = null;
+ }
+ });
+ await DataStore.save(new PostComments(modelFields));
+ if (onSuccess) {
+ onSuccess(modelFields);
+ }
+ if (clearOnSuccess) {
+ resetStateValues();
+ }
+ } catch (err) {
+ if (onError) {
+ onError(modelFields, err.message);
+ }
+ }
+ }}
+ {...getOverrideProps(overrides, "PostCommentsCreateForm")}
+ {...rest}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ s3url: value,
+ users_comments,
+ };
+ const result = onChange(modelFields);
+ value = result?.s3url ?? value;
+ }
+ if (errors.s3url?.hasError) {
+ runValidationTasks("s3url", value);
+ }
+ setS3url(value);
+ }}
+ onBlur={() => runValidationTasks("s3url", s3url)}
+ errorMessage={errors.s3url?.errorMessage}
+ hasError={errors.s3url?.hasError}
+ {...getOverrideProps(overrides, "s3url")}
+ >
+ {
+ let values = items;
+ if (onChange) {
+ const modelFields = {
+ s3url,
+ users_comments: values,
+ };
+ const result = onChange(modelFields);
+ values = result?.users_comments ?? values;
+ }
+ setUsers_comments(values);
+ setCurrentUsers_commentsValue("");
+ }}
+ currentFieldValue={currentUsers_commentsValue}
+ label={"Users comments"}
+ items={users_comments}
+ hasError={errors?.users_comments?.hasError}
+ runValidationTasks={async () =>
+ await runValidationTasks("users_comments", currentUsers_commentsValue)
+ }
+ errorMessage={errors?.users_comments?.errorMessage}
+ setFieldValue={setCurrentUsers_commentsValue}
+ inputFieldRef={users_commentsRef}
+ defaultFieldValue={""}
+ >
+ {
+ let { value } = e.target;
+ if (errors.users_comments?.hasError) {
+ runValidationTasks("users_comments", value);
+ }
+ setCurrentUsers_commentsValue(value);
+ }}
+ onBlur={() =>
+ runValidationTasks("users_comments", currentUsers_commentsValue)
+ }
+ errorMessage={errors.users_comments?.errorMessage}
+ hasError={errors.users_comments?.hasError}
+ ref={users_commentsRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, "users_comments")}
+ >
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/ui-components/PostCommentsUpdateForm.d.ts b/src/ui-components/PostCommentsUpdateForm.d.ts
new file mode 100644
index 0000000..8554156
--- /dev/null
+++ b/src/ui-components/PostCommentsUpdateForm.d.ts
@@ -0,0 +1,41 @@
+/***************************************************************************
+ * The contents of this file were generated with Amplify Studio. *
+ * Please refrain from making any modifications to this file. *
+ * Any changes to this file will be overwritten when running amplify pull. *
+ **************************************************************************/
+
+import * as React from "react";
+import { GridProps, TextAreaFieldProps, TextFieldProps } from "@aws-amplify/ui-react";
+import { EscapeHatchProps } from "@aws-amplify/ui-react/internal";
+import { PostComments } from "../models";
+export declare type ValidationResponse = {
+ hasError: boolean;
+ errorMessage?: string;
+};
+export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
+export declare type PostCommentsUpdateFormInputValues = {
+ s3url?: string;
+ users_comments?: string[];
+};
+export declare type PostCommentsUpdateFormValidationValues = {
+ s3url?: ValidationFunction;
+ users_comments?: ValidationFunction;
+};
+export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
+export declare type PostCommentsUpdateFormOverridesProps = {
+ PostCommentsUpdateFormGrid?: PrimitiveOverrideProps;
+ s3url?: PrimitiveOverrideProps;
+ users_comments?: PrimitiveOverrideProps;
+} & EscapeHatchProps;
+export declare type PostCommentsUpdateFormProps = React.PropsWithChildren<{
+ overrides?: PostCommentsUpdateFormOverridesProps | undefined | null;
+} & {
+ id?: string;
+ postComments?: PostComments;
+ onSubmit?: (fields: PostCommentsUpdateFormInputValues) => PostCommentsUpdateFormInputValues;
+ onSuccess?: (fields: PostCommentsUpdateFormInputValues) => void;
+ onError?: (fields: PostCommentsUpdateFormInputValues, errorMessage: string) => void;
+ onChange?: (fields: PostCommentsUpdateFormInputValues) => PostCommentsUpdateFormInputValues;
+ onValidate?: PostCommentsUpdateFormValidationValues;
+} & React.CSSProperties>;
+export default function PostCommentsUpdateForm(props: PostCommentsUpdateFormProps): React.ReactElement;
diff --git a/src/ui-components/PostCommentsUpdateForm.jsx b/src/ui-components/PostCommentsUpdateForm.jsx
new file mode 100644
index 0000000..250a461
--- /dev/null
+++ b/src/ui-components/PostCommentsUpdateForm.jsx
@@ -0,0 +1,410 @@
+/***************************************************************************
+ * The contents of this file were generated with Amplify Studio. *
+ * Please refrain from making any modifications to this file. *
+ * Any changes to this file will be overwritten when running amplify pull. *
+ **************************************************************************/
+
+/* eslint-disable */
+import * as React from "react";
+import {
+ Badge,
+ Button,
+ Divider,
+ Flex,
+ Grid,
+ Icon,
+ ScrollView,
+ Text,
+ TextAreaField,
+ TextField,
+ useTheme,
+} from "@aws-amplify/ui-react";
+import { getOverrideProps } from "@aws-amplify/ui-react/internal";
+import { PostComments } from "../models";
+import { fetchByPath, validateField } from "./utils";
+import { DataStore } from "aws-amplify";
+function ArrayField({
+ items = [],
+ onChange,
+ label,
+ inputFieldRef,
+ children,
+ hasError,
+ setFieldValue,
+ currentFieldValue,
+ defaultFieldValue,
+ lengthLimit,
+ getBadgeText,
+ runValidationTasks,
+ errorMessage,
+}) {
+ const labelElement = {label};
+ const {
+ tokens: {
+ components: {
+ fieldmessages: { error: errorStyles },
+ },
+ },
+ } = useTheme();
+ const [selectedBadgeIndex, setSelectedBadgeIndex] = React.useState();
+ const [isEditing, setIsEditing] = React.useState();
+ React.useEffect(() => {
+ if (isEditing) {
+ inputFieldRef?.current?.focus();
+ }
+ }, [isEditing]);
+ const removeItem = async (removeIndex) => {
+ const newItems = items.filter((value, index) => index !== removeIndex);
+ await onChange(newItems);
+ setSelectedBadgeIndex(undefined);
+ };
+ const addItem = async () => {
+ const { hasError } = runValidationTasks();
+ if (
+ currentFieldValue !== undefined &&
+ currentFieldValue !== null &&
+ currentFieldValue !== "" &&
+ !hasError
+ ) {
+ const newItems = [...items];
+ if (selectedBadgeIndex !== undefined) {
+ newItems[selectedBadgeIndex] = currentFieldValue;
+ setSelectedBadgeIndex(undefined);
+ } else {
+ newItems.push(currentFieldValue);
+ }
+ await onChange(newItems);
+ setIsEditing(false);
+ }
+ };
+ const arraySection = (
+
+ {!!items?.length && (
+
+ {items.map((value, index) => {
+ return (
+ {
+ setSelectedBadgeIndex(index);
+ setFieldValue(items[index]);
+ setIsEditing(true);
+ }}
+ >
+ {getBadgeText ? getBadgeText(value) : value.toString()}
+ {
+ event.stopPropagation();
+ removeItem(index);
+ }}
+ />
+
+ );
+ })}
+
+ )}
+
+
+ );
+ if (lengthLimit !== undefined && items.length >= lengthLimit && !isEditing) {
+ return (
+
+ {labelElement}
+ {arraySection}
+
+ );
+ }
+ return (
+
+ {labelElement}
+ {isEditing && children}
+ {!isEditing ? (
+ <>
+
+ {errorMessage && hasError && (
+
+ {errorMessage}
+
+ )}
+ >
+ ) : (
+
+ {(currentFieldValue || isEditing) && (
+
+ )}
+
+
+ )}
+ {arraySection}
+
+ );
+}
+export default function PostCommentsUpdateForm(props) {
+ const {
+ id: idProp,
+ postComments: postCommentsModelProp,
+ onSuccess,
+ onError,
+ onSubmit,
+ onValidate,
+ onChange,
+ overrides,
+ ...rest
+ } = props;
+ const initialValues = {
+ s3url: "",
+ users_comments: [],
+ };
+ const [s3url, setS3url] = React.useState(initialValues.s3url);
+ const [users_comments, setUsers_comments] = React.useState(
+ initialValues.users_comments
+ );
+ const [errors, setErrors] = React.useState({});
+ const resetStateValues = () => {
+ const cleanValues = postCommentsRecord
+ ? { ...initialValues, ...postCommentsRecord }
+ : initialValues;
+ setS3url(cleanValues.s3url);
+ setUsers_comments(cleanValues.users_comments ?? []);
+ setCurrentUsers_commentsValue("");
+ setErrors({});
+ };
+ const [postCommentsRecord, setPostCommentsRecord] = React.useState(
+ postCommentsModelProp
+ );
+ React.useEffect(() => {
+ const queryData = async () => {
+ const record = idProp
+ ? await DataStore.query(PostComments, idProp)
+ : postCommentsModelProp;
+ setPostCommentsRecord(record);
+ };
+ queryData();
+ }, [idProp, postCommentsModelProp]);
+ React.useEffect(resetStateValues, [postCommentsRecord]);
+ const [currentUsers_commentsValue, setCurrentUsers_commentsValue] =
+ React.useState("");
+ const users_commentsRef = React.createRef();
+ const validations = {
+ s3url: [{ type: "Required" }],
+ users_comments: [{ type: "Required" }, { type: "JSON" }],
+ };
+ const runValidationTasks = async (
+ fieldName,
+ currentValue,
+ getDisplayValue
+ ) => {
+ const value =
+ currentValue && getDisplayValue
+ ? getDisplayValue(currentValue)
+ : currentValue;
+ let validationResponse = validateField(value, validations[fieldName]);
+ const customValidator = fetchByPath(onValidate, fieldName);
+ if (customValidator) {
+ validationResponse = await customValidator(value, validationResponse);
+ }
+ setErrors((errors) => ({ ...errors, [fieldName]: validationResponse }));
+ return validationResponse;
+ };
+ return (
+ {
+ event.preventDefault();
+ let modelFields = {
+ s3url,
+ users_comments,
+ };
+ const validationResponses = await Promise.all(
+ Object.keys(validations).reduce((promises, fieldName) => {
+ if (Array.isArray(modelFields[fieldName])) {
+ promises.push(
+ ...modelFields[fieldName].map((item) =>
+ runValidationTasks(fieldName, item)
+ )
+ );
+ return promises;
+ }
+ promises.push(
+ runValidationTasks(fieldName, modelFields[fieldName])
+ );
+ return promises;
+ }, [])
+ );
+ if (validationResponses.some((r) => r.hasError)) {
+ return;
+ }
+ if (onSubmit) {
+ modelFields = onSubmit(modelFields);
+ }
+ try {
+ Object.entries(modelFields).forEach(([key, value]) => {
+ if (typeof value === "string" && value === "") {
+ modelFields[key] = null;
+ }
+ });
+ await DataStore.save(
+ PostComments.copyOf(postCommentsRecord, (updated) => {
+ Object.assign(updated, modelFields);
+ })
+ );
+ if (onSuccess) {
+ onSuccess(modelFields);
+ }
+ } catch (err) {
+ if (onError) {
+ onError(modelFields, err.message);
+ }
+ }
+ }}
+ {...getOverrideProps(overrides, "PostCommentsUpdateForm")}
+ {...rest}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ s3url: value,
+ users_comments,
+ };
+ const result = onChange(modelFields);
+ value = result?.s3url ?? value;
+ }
+ if (errors.s3url?.hasError) {
+ runValidationTasks("s3url", value);
+ }
+ setS3url(value);
+ }}
+ onBlur={() => runValidationTasks("s3url", s3url)}
+ errorMessage={errors.s3url?.errorMessage}
+ hasError={errors.s3url?.hasError}
+ {...getOverrideProps(overrides, "s3url")}
+ >
+ {
+ let values = items;
+ if (onChange) {
+ const modelFields = {
+ s3url,
+ users_comments: values,
+ };
+ const result = onChange(modelFields);
+ values = result?.users_comments ?? values;
+ }
+ setUsers_comments(values);
+ setCurrentUsers_commentsValue("");
+ }}
+ currentFieldValue={currentUsers_commentsValue}
+ label={"Users comments"}
+ items={users_comments}
+ hasError={errors?.users_comments?.hasError}
+ runValidationTasks={async () =>
+ await runValidationTasks("users_comments", currentUsers_commentsValue)
+ }
+ errorMessage={errors?.users_comments?.errorMessage}
+ setFieldValue={setCurrentUsers_commentsValue}
+ inputFieldRef={users_commentsRef}
+ defaultFieldValue={""}
+ >
+ {
+ let { value } = e.target;
+ if (errors.users_comments?.hasError) {
+ runValidationTasks("users_comments", value);
+ }
+ setCurrentUsers_commentsValue(value);
+ }}
+ onBlur={() =>
+ runValidationTasks("users_comments", currentUsers_commentsValue)
+ }
+ errorMessage={errors.users_comments?.errorMessage}
+ hasError={errors.users_comments?.hasError}
+ ref={users_commentsRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, "users_comments")}
+ >
+
+
+
+
+
+
+
+
+ );
+}
Comments
+ +