check prev state for modal

This commit is contained in:
vincanger 2023-10-04 12:06:33 +02:00
parent 124a3d4522
commit 3d25c4ae0b
6 changed files with 79 additions and 124 deletions

View File

@ -42,10 +42,6 @@ app waspAi {
userEntity: User,
externalAuthEntity: SocialLogin,
methods: {
gitHub: {
configFn: import { getGitHubAuthConfig } from "@server/auth.js",
getUserFieldsFn: import { getGitHubUserFields } from "@server/auth.js",
},
google: {
configFn: import { getGoogleAuthConfig } from "@server/auth.js",
getUserFieldsFn: import { getGoogleUserFields } from "@server/auth.js",

View File

@ -1,7 +1,5 @@
import { StatusPill } from './StatusPill';
import { Title } from './Title';
import { signInUrl as gitHubSignInUrl } from '@wasp/auth/helpers/GitHub';
import { AiFillGithub } from 'react-icons/ai';
export function Header({ currentStatus, isStatusVisible }) {
return (
@ -14,12 +12,4 @@ export function Header({ currentStatus, isStatusVisible }) {
)}
</div>
);
}
function GithubLoginButton() {
return (
<button className='button gray flex !text-gray-800 hover:bg-slate-300 shadow-md' onClick={() => window.location.href = gitHubSignInUrl}>
<AiFillGithub className='w-6 h-6 mr-2' /> Sign in with GitHub
</button>
)
}

View File

@ -14,7 +14,7 @@ import { MyDialog } from "../components/Dialog";
const MainPage = () => {
const [appName, setAppName] = useState("");
const [appDesc, setAppDesc] = useState("");
const [isGhModalOpen, setIsGhModalOpen] = useState(false);
const [isPowerUserModalOpen, setIsPowerUserModalOpen] = useState(false);
const [currentStatus, setCurrentStatus] = useState({
status: "idle",
message: "Waiting for instructions",
@ -78,7 +78,7 @@ const MainPage = () => {
localStorage.setItem("appNum", 0);
}
if (appNum === 2) {
setIsGhModalOpen(true);
setIsPowerUserModalOpen(true);
}
if (appDetails) {
setAppName(appDetails.appName);
@ -151,7 +151,7 @@ const MainPage = () => {
<div className="container">
<Header currentStatus={currentStatus} isStatusVisible={true} />
<GhModal isGhModalOpen={isGhModalOpen} setIsGhModalOpen={setIsGhModalOpen} />
<PowerUserModal isOpen={isPowerUserModalOpen} setIsOpen={setIsPowerUserModalOpen} />
<form onSubmit={startGenerating} className="bg-slate-50 p-8 rounded-xl">
<div className="mb-6 flex flex-col gap-3">
@ -188,64 +188,38 @@ The simpler and more specific the app is, the better the generated app will be."
</div>
<div className="grid md:grid-cols-3 gap-3">
<div>
<label
htmlFor="appPrimaryColor"
className="text-slate-700 block mb-2"
>
<label htmlFor="appPrimaryColor" className="text-slate-700 block mb-2">
App brand color
</label>
<MyDropdown
value={appPrimaryColor}
onChange={setAppPrimaryColor}
options={availableColors}
/>
<MyDropdown value={appPrimaryColor} onChange={setAppPrimaryColor} options={availableColors} />
</div>
<div>
<label
htmlFor="creativityLevel"
className="text-slate-700 block mb-2"
>
<label htmlFor="creativityLevel" className="text-slate-700 block mb-2">
Creativity level
</label>
<MyDropdown
value={creativityLevel}
onChange={setCreativityLevel}
options={availableCreativityLevels}
/>
<MyDropdown value={creativityLevel} onChange={setCreativityLevel} options={availableCreativityLevels} />
</div>
<div>
<label
htmlFor="appAuthMethod"
className="text-slate-700 block mb-2"
>
<label htmlFor="appAuthMethod" className="text-slate-700 block mb-2">
Auth method
</label>
<MyDropdown
value={appAuthMethod}
onChange={setAppAuthMethod}
options={availableAuthMethods}
/>
<MyDropdown value={appAuthMethod} onChange={setAppAuthMethod} options={availableAuthMethods} />
</div>
</div>
</div>
<button
className="button mr-2"
disabled={currentStatus.status === "inProgress"}
>
<button className="button mr-2" disabled={currentStatus.status === "inProgress"}>
Generate the app <PiMagicWandDuotone className="inline-block ml-1" />
</button>
</form>
<div className="mt-8">
<h3 className="text-xl font-semibold mb-4 text-slate-800">
Some example ideas
</h3>
<h3 className="text-xl font-semibold mb-4 text-slate-800">Some example ideas</h3>
<div className="grid grid-cols-1 gap-2 lg:grid-cols-3 lg:gap-4">
{exampleIdeas.map((idea) => (
<ExampleCard key={idea.name} idea={idea} useIdea={useIdea} />
))}
</div>
<div className="mt-8">
<Faq/>
<Faq />
</div>
</div>
</div>
@ -253,9 +227,9 @@ The simpler and more specific the app is, the better the generated app will be."
};
export default MainPage;
export function GhModal({ isGhModalOpen, setIsGhModalOpen }) {
export function PowerUserModal({ isOpen, setIsOpen }) {
return (
<MyDialog isOpen={isGhModalOpen} onClose={() => setIsGhModalOpen(false)} title={<span>With Great Power Comes Great Responsibility! 🧙</span>}>
<MyDialog isOpen={isOpen} onClose={() => setIsOpen(false)} title={<span>With Great Power Comes Great Responsibility! 🧙</span>}>
<div className="mt-6 space-y-5">
<p className="text-base leading-relaxed text-gray-500">
We've made this tool completely <span className="font-semibold">free</span> and cover all the costs 😇

View File

@ -34,7 +34,8 @@ const jsConfetti = new JSConfetti();
export const ResultPage = () => {
const { appId } = useParams();
const [generationDone, setGenerationDone] = useState(false);
const [isStarRepoOpen, setIsStarRepoOpen] = useState(false);
const [isRunning, setIsRunning] = useState(false);
const [isSuccessModalOpen, setIsSuccessModalOpen] = useState(false);
const {
data: appGenerationResult,
isError,
@ -46,7 +47,7 @@ export const ResultPage = () => {
);
const [activeFilePath, setActiveFilePath] = useState(null);
const [currentStatus, setCurrentStatus] = useState({
status: "idle",
status: "idle",
message: "Waiting",
});
const [currentFiles, setCurrentFiles] = useState({});
@ -73,10 +74,16 @@ export const ResultPage = () => {
}, [appId]);
useEffect(() => {
if (currentStatus.status === "success") {
setIsStarRepoOpen(true);
const currentAppStatus = appGenerationResult?.project?.status;
if (currentAppStatus === "in-progress") {
setIsRunning(true)
} else if (currentAppStatus === "success" && isRunning) {
setIsSuccessModalOpen(true)
setIsRunning(false)
} else if (isRunning) {
setIsRunning(false)
}
}, [currentStatus])
}, [appGenerationResult?.project?.status])
const logs = appGenerationResult?.project?.logs.map((log) => log.content);
@ -217,7 +224,7 @@ export const ResultPage = () => {
currentStatus={currentStatus}
isStatusVisible={!!appGenerationResult?.project}
/>
<StarOurRepoModal isStarRepoOpen={isStarRepoOpen} setIsStarRepoOpen={setIsStarRepoOpen} appGenerationResult={appGenerationResult}/>
<OnSuccessModal isOpen={isSuccessModalOpen} setIsOpen={setIsSuccessModalOpen} appGenerationResult={appGenerationResult}/>
{isError && (
<div className="mb-4 bg-red-50 p-8 rounded-xl">
@ -406,59 +413,71 @@ function getCardinalNumber(number) {
}
}
export function StarOurRepoModal({ isStarRepoOpen, setIsStarRepoOpen, appGenerationResult }) {
const [tokens, setTokens] = useState(0)
const { data: numTotalProjects } = useQuery(getNumProjects, {}, { enabled: isStarRepoOpen })
const tokenNumberStr = appGenerationResult?.project?.logs?.filter(log => log.content.toLowerCase().includes("tokens usage") === true)[0]?.content.split(':')[1]?.trim()
export function OnSuccessModal({ isOpen, setIsOpen, appGenerationResult }) {
const [numTokensSpent, setNumTokensSpent] = useState(0)
const { data: numTotalProjects } = useQuery(getNumProjects, {}, { enabled: isOpen })
useEffect(() => {
if (!!tokenNumberStr) {
const num = tokenNumberStr.slice(1, -1) * 1000
setTokens(num)
const logText = appGenerationResult?.project?.logs?.find((log) => /tokens usage/i.test(log.content))?.content;
const tokenNumberStr = logText ? logText.split(":")[1]?.trim() : null;
if (tokenNumberStr) {
const num = Number(tokenNumberStr.replace(/[\s~k]/gi, '')) * 1000;
if (num.toString().match(/^[0-9]+$/)) {
setNumTokensSpent(num);
}
}
}, [tokenNumberStr])
}, [appGenerationResult]);
useEffect(() => {
if (isStarRepoOpen) {
if (isOpen) {
jsConfetti.addConfetti({
emojis: ['🐝'],
emojiSize: 120,
})
}
}, [isStarRepoOpen])
}, [isOpen])
function FormattedText({ children }) {
return <span className="py-1 px-2 font-semibold text-pink-800 rounded">{children}</span>;
}
return (
<MyDialog isOpen={isStarRepoOpen} onClose={() => setIsStarRepoOpen(false)} title={<span>Your App is Ready! 🎉</span>}>
<MyDialog isOpen={isOpen} onClose={() => setIsOpen(false)} title={<span>Your App is Ready! 🎉</span>}>
<div className="mt-6 space-y-5">
<p className="text-base leading-relaxed text-gray-500">
We've made this tool completely <span className="font-semibold">free</span> and cover all the costs 😇
</p>
<table className="bg-slate-50 rounded-lg divide-y divide-gray-100 w-full text-base leading-relaxed text-gray-500 text-sm">
{/* <caption>Fun Stats</caption> */}
<tr>
<td className="p-2 text-gray-600"> Number of tokens your app used: </td>
<td className="p-2 text-gray-600">
{" "}
<FormattedText>{tokens.toLocaleString(2) ?? "~22k"}</FormattedText>{" "}
</td>
</tr>
<tr>
<td className="p-2 text-gray-600"> Cost to generate your app: </td>
<td className="p-2 text-gray-600">
{" "}
<FormattedText>{tokens ? `$${((tokens / 1000) * 0.004).toFixed(2)}` : "~ $0.50"}</FormattedText>{" "}
</td>
</tr>
{numTotalProjects && (
<tr className="p-2 text-gray-600">
<td className="p-2 text-gray-600"> Total number of apps generated with Mage: </td>
<td className="p-2 text-gray-600">
{" "}
<FormattedText>{numTotalProjects.toLocaleString()}</FormattedText>{" "}
</td>
</tr>
)}
</table>
{numTokensSpent && (
<table className="bg-slate-50 rounded-lg divide-y divide-gray-100 w-full text-base leading-relaxed text-gray-500 text-sm">
<tbody>
<tr>
<td className="p-2 text-gray-600"> Number of tokens your app used: </td>
<td className="p-2 text-gray-600">
{" "}
<FormattedText>{numTokensSpent.toLocaleString()}</FormattedText>{" "}
</td>
</tr>
<tr>
<td className="p-2 text-gray-600"> Cost to generate your app: </td>
<td className="p-2 text-gray-600">
{" "}
<FormattedText>
{`$${((Number(numTokensSpent) / 1000) * 0.004).toFixed(2)}`}
</FormattedText>{" "}
</td>
</tr>
{numTotalProjects && (
<tr className="p-2 text-gray-600">
<td className="p-2 text-gray-600"> Total number of apps generated with Mage: </td>
<td className="p-2 text-gray-600">
{" "}
<FormattedText>{numTotalProjects.toLocaleString()}</FormattedText>{" "}
</td>
</tr>
)}
</tbody>
</table>
)}
<p className="text-base leading-relaxed text-gray-500">
But you can still show your support by starring us on GitHub:
</p>
@ -478,15 +497,9 @@ export function StarOurRepoModal({ isStarRepoOpen, setIsStarRepoOpen, appGenerat
<p className="text-base leading-relaxed text-gray-500">We'd very much appreciate it! 🧙</p>
</div>
</MyDialog>
)
);
}
function FormattedText({ children }) {
return (
<span className='py-1 px-2 font-semibold text-pink-800 rounded'>{children}</span>
)
}
export default function RunTheAppModal({ disabled, onDownloadZip }) {
const [showModal, setShowModal] = useState(false);
return (

View File

@ -13,19 +13,3 @@ export const getGoogleAuthConfig = () => {
scope: ["profile", "email"],
};
};
export const getGitHubUserFields: GetUserFieldsFn = async (_context, args) => {
// NOTE: if we don't want to access users' emails, we can use scope ["user:read"]
// instead of ["user"] and access args.profile.username instead
const email = args.profile.emails[0].value;
return { email };
};
export function getGitHubAuthConfig() {
return {
clientID: process.env.GITHUB_CLIENT_ID, // look up from env or elsewhere
clientSecret: process.env.GITHUB_CLIENT_SECRET, // look up from env or elsewhere
scope: ["user"],
};
}

View File

@ -225,9 +225,7 @@ export const getStats = (async (_args, context) => {
}) satisfies GetStats<{}>;
export const getNumProjects = (async (_args, context) => {
const { Project } = context.entities;
const numProjects = await Project.count();
return numProjects;
return context.entities.Project.count();
}) satisfies GetNumProjects<{}>;
function getDownloadStats(projects: Project[]) {