Compare commits

...

7 Commits

Author SHA1 Message Date
bb4fbc3700 Merge branch 'main' into sgunter/feat-preserve-email-on-feedback-form 2025-10-30 19:21:05 -05:00
dependabot[bot]
e8a8b8e1ae chore(deps): bump the npm_and_yarn group across 1 directory with 4 updates (#639)
Bumps the npm_and_yarn group with 4 updates in the / directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite), [@babel/helpers](https://github.com/babel/babel/tree/HEAD/packages/babel-helpers), [brace-expansion](https://github.com/juliangruber/brace-expansion) and [undici](https://github.com/nodejs/undici).


Updates `vite` from 5.4.14 to 5.4.20
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.20/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.20/packages/vite)

Updates `@babel/helpers` from 7.26.9 to 7.28.4
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.28.4/packages/babel-helpers)

Updates `brace-expansion` from 1.1.11 to 1.1.12
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v1.1.12)

Updates `undici` from 6.21.1 to 6.22.0
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v6.21.1...v6.22.0)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 5.4.20
  dependency-type: direct:development
  dependency-group: npm_and_yarn
- dependency-name: "@babel/helpers"
  dependency-version: 7.28.4
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: brace-expansion
  dependency-version: 1.1.12
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: undici
  dependency-version: 6.22.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-13 11:36:53 -05:00
doprz
35d903e7c8 Merge branch 'main' into sgunter/feat-preserve-email-on-feedback-form 2025-08-27 21:31:17 -07:00
Samuel Gunter
1fffb3c2e7 Merge branch 'main' into sgunter/feat-preserve-email-on-feedback-form 2025-08-12 14:28:29 -05:00
doprz
4590a74896 Merge branch 'main' into sgunter/feat-preserve-email-on-feedback-form 2025-08-12 13:45:49 -05:00
190d1db2fa Merge branch 'main' into sgunter/feat-preserve-email-on-feedback-form 2025-06-18 01:58:26 -05:00
Samuel Gunter
b8a44b45b8 feat: preserve email on feedback form, optionally 2025-06-08 23:48:28 -07:00
5 changed files with 685 additions and 372 deletions

View File

@@ -144,7 +144,7 @@
"unocss": "^0.63.6", "unocss": "^0.63.6",
"unocss-preset-primitives": "0.0.2-beta.1", "unocss-preset-primitives": "0.0.2-beta.1",
"unplugin-icons": "^0.19.3", "unplugin-icons": "^0.19.3",
"vite": "^5.4.14", "vite": "^5.4.20",
"vite-plugin-inspect": "^0.8.9", "vite-plugin-inspect": "^0.8.9",
"vitest": "^2.1.9" "vitest": "^2.1.9"
}, },

935
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot';
import ReportIssueMain from '@views/components/ReportIssueMain'; import ReportIssueMain from '@views/components/ReportIssueMain';
import SentryProvider from '@views/contexts/SentryContext'; import SentryProvider from '@views/contexts/SentryContext';
import React from 'react'; import React from 'react';
@@ -5,6 +6,8 @@ import { createRoot } from 'react-dom/client';
createRoot(document.getElementById('root')!).render( createRoot(document.getElementById('root')!).render(
<SentryProvider fullInit> <SentryProvider fullInit>
<ReportIssueMain /> <ExtensionRoot>
<ReportIssueMain />
</ExtensionRoot>
</SentryProvider> </SentryProvider>
); );

View File

@@ -24,6 +24,12 @@ export interface IOptionsStore {
/** whether the promo should be shown */ /** whether the promo should be shown */
showUTDiningPromo: boolean; showUTDiningPromo: boolean;
/** whether the user's email address should be remembered by the extension */
rememberMyEmail: boolean;
/** the user's email address, if set and chosen to be remembered */
emailAddress: string;
} }
export const OptionsStore = createSyncStore<IOptionsStore>({ export const OptionsStore = createSyncStore<IOptionsStore>({
@@ -34,6 +40,8 @@ export const OptionsStore = createSyncStore<IOptionsStore>({
alwaysOpenCalendarInNewTab: false, alwaysOpenCalendarInNewTab: false,
showCalendarSidebar: true, showCalendarSidebar: true,
showUTDiningPromo: true, showUTDiningPromo: true,
rememberMyEmail: false,
emailAddress: '',
}); });
/** /**
@@ -50,6 +58,8 @@ export const initSettings = async () =>
alwaysOpenCalendarInNewTab: await OptionsStore.get('alwaysOpenCalendarInNewTab'), alwaysOpenCalendarInNewTab: await OptionsStore.get('alwaysOpenCalendarInNewTab'),
showCalendarSidebar: await OptionsStore.get('showCalendarSidebar'), showCalendarSidebar: await OptionsStore.get('showCalendarSidebar'),
showUTDiningPromo: await OptionsStore.get('showUTDiningPromo'), showUTDiningPromo: await OptionsStore.get('showUTDiningPromo'),
rememberMyEmail: await OptionsStore.get('rememberMyEmail'),
emailAddress: await OptionsStore.get('emailAddress'),
}) satisfies IOptionsStore; }) satisfies IOptionsStore;
// Clothing retailer right // Clothing retailer right

View File

@@ -1,6 +1,8 @@
import 'uno.css'; import 'uno.css';
import { captureFeedback } from '@sentry/react'; import { captureFeedback } from '@sentry/react';
import { OptionsStore } from '@shared/storage/OptionsStore';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Button } from './common/Button'; import { Button } from './common/Button';
@@ -12,19 +14,57 @@ import Text from './common/Text/Text';
* @returns The rendered component. * @returns The rendered component.
*/ */
export default function ReportIssueMain(): JSX.Element { export default function ReportIssueMain(): JSX.Element {
const [email, setEmail] = useState(''); const queryClient = useQueryClient();
const { data: emailAddress } = useQuery({
queryKey: ['settings', 'emailAddress'],
queryFn: () => OptionsStore.get('emailAddress'),
staleTime: Infinity, // Prevent loading state on refocus
});
const { mutate: setEmailAddress } = useMutation({
mutationKey: ['settings', 'emailAddress'],
mutationFn: async ({ rememberMyEmail, emailAddress }: { rememberMyEmail: boolean; emailAddress: string }) => {
queryClient.setQueryData(['settings', 'emailAddress'], emailAddress);
if (rememberMyEmail) {
OptionsStore.set('emailAddress', emailAddress);
}
},
});
const { data: rememberMyEmail } = useQuery({
queryKey: ['settings', 'rememberMyEmail'],
queryFn: () => OptionsStore.get('rememberMyEmail'),
staleTime: Infinity, // Prevent loading state on refocus
});
const { mutate: setRememberMyEmail } = useMutation({
mutationKey: ['settings', 'rememberMyEmail'],
mutationFn: async ({ rememberMyEmail, emailAddress }: { rememberMyEmail: boolean; emailAddress: string }) => {
queryClient.setQueryData(['settings', 'rememberMyEmail'], rememberMyEmail);
OptionsStore.set('rememberMyEmail', rememberMyEmail);
if (rememberMyEmail) {
OptionsStore.set('emailAddress', emailAddress);
} else {
OptionsStore.set('emailAddress', '');
}
},
});
const [feedback, setFeedback] = useState(''); const [feedback, setFeedback] = useState('');
const [isSubmitted, setIsSubmitted] = useState(false); const [isSubmitted, setIsSubmitted] = useState(false);
const submitFeedback = async () => { const submitFeedback = async () => {
if (!email || !feedback) { if (!emailAddress || !feedback) {
throw new Error('Email and feedback are required'); throw new Error('Email and feedback are required');
} }
// Here you would typically send the feedback to a server
await captureFeedback( // Send the feedback to Sentry
captureFeedback(
{ {
message: feedback || 'No feedback provided', message: feedback || 'No feedback provided',
email, email: emailAddress,
tags: { tags: {
version: chrome.runtime.getManifest().version, version: chrome.runtime.getManifest().version,
}, },
@@ -34,16 +74,14 @@ export default function ReportIssueMain(): JSX.Element {
} }
); );
// Reset form fields and close the dialog // Close the dialog
setEmail('');
setFeedback('');
setIsSubmitted(true); setIsSubmitted(true);
}; };
if (isSubmitted) { if (isSubmitted) {
return ( return (
<div className='w-80 flex flex-col rounded-lg bg-white p-6 shadow-lg'> <div className='w-92 flex flex-col rounded-lg bg-white p-6 shadow-lg'>
<Text variant='h2' className='mb-4'> <Text variant='h2' className='my-4'>
Thank you Thank you
</Text> </Text>
<Text variant='p' className='mb-6'> <Text variant='p' className='mb-6'>
@@ -56,28 +94,13 @@ export default function ReportIssueMain(): JSX.Element {
); );
} }
if (isSubmitted) {
return (
<div className='w-80 bg-white p-6'>
<h2 className='mb-4 text-2xl text-orange font-bold'>{`Hook'em Horns!`}</h2>
<p className='mb-6 text-gray-600'>Your feedback is music to our ears. Thanks for helping us improve!</p>
<button
className='w-full rounded bg-orange-600 px-4 py-2 text-white font-bold transition duration-300 hover:bg-orange-700'
onClick={() => window.close()}
>
Close
</button>
</div>
);
}
return ( return (
<div className='w-80 bg-white p-6'> <div className='w-92 bg-white p-6'>
<h2 className='mb-4 text-2xl text-ut-burntorange font-bold'>Longhorn Feedback</h2> <h2 className='my-4 text-2xl text-ut-burntorange font-bold'>Longhorn Feedback</h2>
<p className='mb-4 text-sm text-ut-black'>Help us make UT Registration Plus even better!</p> <p className='mb-4 text-sm text-ut-black'>Help us make UT Registration Plus even better!</p>
<form onSubmit={submitFeedback}> <form onSubmit={submitFeedback}>
<div className='mb-4'> <div className='mb-1'>
<label htmlFor='email' className='mb-1 block text-sm text-ut-black font-medium'> <label htmlFor='email' className='mb-1 block text-sm text-ut-black font-medium'>
Your @utexas.edu email Your @utexas.edu email
</label> </label>
@@ -85,8 +108,13 @@ export default function ReportIssueMain(): JSX.Element {
<input <input
type='email' type='email'
id='email' id='email'
value={email} value={emailAddress}
onChange={e => setEmail(e.target.value)} onChange={e =>
setEmailAddress({
emailAddress: e.target.value,
rememberMyEmail: rememberMyEmail ?? false,
})
}
className='w-full border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-orange-500' className='w-full border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-orange-500'
placeholder='bevo@utexas.edu' placeholder='bevo@utexas.edu'
required required
@@ -94,6 +122,23 @@ export default function ReportIssueMain(): JSX.Element {
</div> </div>
</div> </div>
<div className='mb-4'>
<label className='mb-1 flex cursor-pointer content-center gap-1.25 text-sm text-ut-black font-medium'>
<input
type='checkbox'
className='cursor-pointer'
checked={rememberMyEmail}
onChange={e =>
setRememberMyEmail({
rememberMyEmail: e.target.checked,
emailAddress: emailAddress ?? '',
})
}
/>{' '}
Remember my email
</label>
</div>
<div className='mb-4'> <div className='mb-4'>
<label htmlFor='feedback' className='mb-1 block text-sm text-ut-black font-medium'> <label htmlFor='feedback' className='mb-1 block text-sm text-ut-black font-medium'>
Your feedback Your feedback