-
Notifications
You must be signed in to change notification settings - Fork 19
fix: report feature improvements and bug fixes #530
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| import { t } from "@lingui/core/macro"; | ||
| import { Trans } from "@lingui/react/macro"; | ||
| import { | ||
| Anchor, | ||
| Button, | ||
| Divider, | ||
| Group, | ||
| Modal, | ||
| rem, | ||
| Stack, | ||
| Text, | ||
| } from "@mantine/core"; | ||
| import { getProductFeedbackUrl } from "@/config"; | ||
| import { QRCode } from "./QRCode"; | ||
|
|
||
| interface FeedbackPortalModalProps { | ||
| opened: boolean; | ||
| onClose: () => void; | ||
| locale?: string; | ||
| } | ||
|
|
||
| export const FeedbackPortalModal = ({ | ||
| opened, | ||
| onClose, | ||
| locale, | ||
| }: FeedbackPortalModalProps) => { | ||
| const feedbackUrl = getProductFeedbackUrl(locale); | ||
|
|
||
| const actionButtonStyles = { | ||
| root: { | ||
| minHeight: rem(40), | ||
| paddingBottom: rem(10), | ||
| paddingLeft: rem(20), | ||
| paddingRight: rem(20), | ||
| paddingTop: rem(10), | ||
| }, | ||
| } as const; | ||
|
|
||
| return ( | ||
| <Modal | ||
| opened={opened} | ||
| onClose={onClose} | ||
| title={t`Feedback portal`} | ||
| centered | ||
| > | ||
| <Stack gap="lg"> | ||
| <Stack gap="md"> | ||
| <Text size="sm"> | ||
| <Trans> | ||
| We'd love to hear from you. Whether you have an idea for something | ||
| new, you've hit a bug, spotted a translation that feels off, or | ||
| just want to share how things have been going. | ||
| </Trans> | ||
| </Text> | ||
| <Text size="sm"> | ||
| <Trans> | ||
| To help us act on it, try to include where it happened and what | ||
| you were trying to do. For bugs, tell us what went wrong. For | ||
| ideas, tell us what need it would solve for you. | ||
| </Trans> | ||
| </Text> | ||
| <Text size="sm"> | ||
| <Trans> | ||
| Just talk or type naturally. Your input goes directly to our | ||
| product team and genuinely helps us make dembrane better. We read | ||
| everything. | ||
| </Trans> | ||
| </Text> | ||
| </Stack> | ||
|
|
||
| <Group align="center" gap="lg" wrap="nowrap"> | ||
| <QRCode | ||
| value={feedbackUrl} | ||
| href={feedbackUrl} | ||
| className="h-auto w-full min-w-[80px] max-w-[128px]" | ||
| /> | ||
| <Stack gap={4}> | ||
| <Text fw={600}> | ||
| <Trans>Scan or click to open the feedback portal</Trans> | ||
| </Text> | ||
| <Group gap="xs"> | ||
| <Text size="xs" c="dimmed"> | ||
| <Trans>Or prefer to chat directly?</Trans> | ||
| </Text> | ||
| <Anchor | ||
| href="https://cal.com/sameer-dembrane" | ||
| target="_blank" | ||
| size="xs" | ||
| > | ||
| <Trans>Book a call with us</Trans> | ||
| </Anchor> | ||
| </Group> | ||
| </Stack> | ||
| </Group> | ||
|
|
||
| <Divider /> | ||
|
|
||
| <Group justify="flex-end" gap="sm" align="center"> | ||
| <Button | ||
| variant="default" | ||
| size="md" | ||
| onClick={onClose} | ||
| styles={actionButtonStyles} | ||
| > | ||
| <Trans>Cancel</Trans> | ||
| </Button> | ||
| </Group> | ||
| </Stack> | ||
| </Modal> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,32 @@ | ||
| import { rem } from "@mantine/core"; | ||
| import { IconExternalLink } from "@tabler/icons-react"; | ||
| import { type CSSProperties, type Ref, useState } from "react"; | ||
| import { QRCode as Q } from "react-qrcode-logo"; | ||
|
|
||
| import { CURRENT_BRAND } from "./Logo"; | ||
|
|
||
| /** | ||
| * QRCode component | ||
| * Try to wrap this component in a div with a fixed width and height | ||
| */ | ||
| export const QRCode = (props: { value: string; ref?: any }) => { | ||
| return ( | ||
| interface QRCodeProps { | ||
| value: string; | ||
| href?: string; | ||
| ref?: Ref<HTMLDivElement>; | ||
| className?: string; | ||
| style?: CSSProperties; | ||
| "data-testid"?: string; | ||
| } | ||
|
|
||
| export const QRCode = ({ | ||
| value, | ||
| href, | ||
| ref, | ||
| className, | ||
| style, | ||
| "data-testid": dataTestId, | ||
| }: QRCodeProps) => { | ||
| const [hovered, setHovered] = useState(false); | ||
|
|
||
| const qrElement = ( | ||
| <Q | ||
| value={props.value} | ||
| ref={props.ref} | ||
| value={value} | ||
| logoImage={ | ||
| CURRENT_BRAND === "dembrane" | ||
| ? "/dembrane-logomark-cropped.png" | ||
|
|
@@ -29,4 +45,42 @@ export const QRCode = (props: { value: string; ref?: any }) => { | |
| }} | ||
| /> | ||
| ); | ||
|
|
||
| if (!href) { | ||
| return ( | ||
| <div ref={ref} className={className} style={style} data-testid={dataTestId}> | ||
| {qrElement} | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| return ( | ||
| <a | ||
| ref={ref as Ref<HTMLAnchorElement>} | ||
| href={href} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className={`relative block cursor-pointer overflow-hidden rounded-lg bg-white transition-all ${className ?? ""}`} | ||
| style={style} | ||
| data-testid={dataTestId} | ||
| onMouseEnter={() => setHovered(true)} | ||
| onMouseLeave={() => setHovered(false)} | ||
| > | ||
| {qrElement} | ||
| <div | ||
| className="absolute inset-0 flex items-center justify-center rounded-lg transition-all print:hidden" | ||
| style={{ | ||
| backgroundColor: hovered | ||
| ? "rgba(65, 105, 225, 0.85)" | ||
| : "transparent", | ||
|
Comment on lines
+63
to
+75
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace hardcoded QR colors with theme tokens/CSS variables.
As per coding guidelines: Also applies to: 81-81 🤖 Prompt for AI Agents |
||
| opacity: hovered ? 1 : 0, | ||
| }} | ||
| > | ||
| <IconExternalLink | ||
| style={{ height: rem(32), width: rem(32) }} | ||
| color="white" | ||
| /> | ||
| </div> | ||
| </a> | ||
| ); | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trim the modal copy.
This is a lot of text for a single decision point, and it reads heavier than the rest of the app. I'd compress this to one short intro plus one short “what to include” hint. As per coding guidelines "use shortest possible copy with highest clarity, avoid jargon and corporate speak, write like explaining to a colleague".
🤖 Prompt for AI Agents