diff --git a/wasp-ai/main.wasp b/wasp-ai/main.wasp index 26e4ff082..a5c7ea0f0 100644 --- a/wasp-ai/main.wasp +++ b/wasp-ai/main.wasp @@ -63,6 +63,12 @@ page StatsPage { authRequired: true } +route FeedbackRoute { path: "/feedback", to: FeedbackPage } +page FeedbackPage { + component: import { Feedback } from "@client/pages/FeedbackPage.jsx", + authRequired: true +} + route LoginRoute { path: "/login", to: LoginPage } page LoginPage { component: import { LoginPage } from "@client/pages/LoginPage.jsx", @@ -80,6 +86,17 @@ action registerZipDownload { entities: [Project] } +action createFeedback { + fn: import { createFeedback } from "@server/operations.js", + entities: [Feedback] +} + +query getFeedback { + fn: import { getFeedback } from "@server/operations.js", + entities: [Feedback] +} + + query getAppGenerationResult { fn: import { getAppGenerationResult } from "@server/operations.js", entities: [ @@ -127,6 +144,17 @@ entity Project {=psl user User? @relation(fields: [userId], references: [id]) files File[] logs Log[] + feedbacks Feedback[] +psl=} + +entity Feedback {=psl + id String @id @default(uuid()) + score Int + message String + createdAt DateTime @default(now()) + + projectId String + project Project @relation(fields: [projectId], references: [id]) psl=} entity File {=psl diff --git a/wasp-ai/migrations/20230715114712_added_feedback_entity/migration.sql b/wasp-ai/migrations/20230715114712_added_feedback_entity/migration.sql new file mode 100644 index 000000000..ad7943379 --- /dev/null +++ b/wasp-ai/migrations/20230715114712_added_feedback_entity/migration.sql @@ -0,0 +1,12 @@ +-- CreateTable +CREATE TABLE "Feedback" ( + "id" TEXT NOT NULL, + "score" INTEGER NOT NULL, + "message" TEXT NOT NULL, + "projectId" TEXT NOT NULL, + + CONSTRAINT "Feedback_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "Feedback" ADD CONSTRAINT "Feedback_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/wasp-ai/migrations/20230715131955_added_created_at_to_feedback_entity/migration.sql b/wasp-ai/migrations/20230715131955_added_created_at_to_feedback_entity/migration.sql new file mode 100644 index 000000000..c2a79651a --- /dev/null +++ b/wasp-ai/migrations/20230715131955_added_created_at_to_feedback_entity/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Feedback" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; diff --git a/wasp-ai/src/client/pages/FeedbackPage.jsx b/wasp-ai/src/client/pages/FeedbackPage.jsx new file mode 100644 index 000000000..46c341030 --- /dev/null +++ b/wasp-ai/src/client/pages/FeedbackPage.jsx @@ -0,0 +1,82 @@ +import { useState, useMemo } from "react"; +import getFeedback from "@wasp/queries/getFeedback"; +import { useQuery } from "@wasp/queries"; +import { Link } from "react-router-dom"; +import { format } from "timeago.js"; + +export function Feedback() { + const { data: feedback, isLoading, error } = useQuery(getFeedback); + + console.log(feedback) + + return ( + <> + {isLoading &&

Loading...

} + + {error &&

Error: {error.message}

} + + {feedback && feedback.feedbackEntries.length === 0 && ( +

No feedback yet.

+ )} + + {feedback && feedback.feedbackEntries.length > 0 && ( +
+ + + + + + + + + + + + {feedback.feedbackEntries.map((entry, idx) => ( + + + + + + + + ))} + +
+ App Name + + Created At + + Score + + Message +
+ {entry.project.name}{" "} + + {format(entry.createdAt)} + + {entry.score} + + {entry.message} + + + View the app → + +
+
+ )} + + ) +} \ No newline at end of file diff --git a/wasp-ai/src/client/pages/ResultPage.jsx b/wasp-ai/src/client/pages/ResultPage.jsx index ba7d67cac..0f56b16cb 100644 --- a/wasp-ai/src/client/pages/ResultPage.jsx +++ b/wasp-ai/src/client/pages/ResultPage.jsx @@ -2,6 +2,7 @@ import { useState, useEffect, useMemo } from "react"; import getAppGenerationResult from "@wasp/queries/getAppGenerationResult"; import startGeneratingNewApp from "@wasp/actions/startGeneratingNewApp"; import registerZipDownload from "@wasp/actions/registerZipDownload"; +import createFeedback from "@wasp/actions/createFeedback" import { useQuery } from "@wasp/queries"; import { CodeHighlight } from "../components/CodeHighlight"; import { FileTree } from "../components/FileTree"; @@ -9,6 +10,7 @@ import { createFilesAndDownloadZip } from "../zip/zipHelpers"; import { useParams } from "react-router-dom"; import { Link } from "react-router-dom"; import { useHistory } from "react-router-dom"; +import { RadioGroup } from '@headlessui/react' import { Loader } from "../components/Loader"; import { MyDialog } from "../components/Dialog"; import { Logs } from "../components/Logs"; @@ -20,6 +22,7 @@ import { PiLaptopDuotone, PiDownloadDuotone, PiCheckDuotone, + PiChatBold } from "react-icons/pi"; import { RxQuestionMarkCircled } from "react-icons/rx"; @@ -287,6 +290,7 @@ export const ResultPage = () => {
+ {
-
- {activeFilePath}: +
+ {activeFilePath}: + +
{ + e.preventDefault() + + console.log(score, feedbackText, projectId) + + try { + await createFeedback({ score, message: feedbackText, projectId }) + } catch (e) { + console.error('Could not create feedback') + } + + setIsModalOpened(false) + setScore(0) + setFeedbackText('') + } + + return ( +
+ + setIsModalOpened(false)} + title={ + + Let us know how it went! + + } + > +
+ +
+ +
+ {scoreOptions.map((option) => ( + + {({ active, checked }) => ( +
+ {option} +
+ )} +
+ ))} +
+
+
+ + + +