Skip to content

Commit

Permalink
🖼️ Able to set background pattern image for pro users (#yoginth/eng-9…
Browse files Browse the repository at this point in the history
…9-able-to-set-background-pattern-image-for-pro-users)

Summary: Added functionality for pro users to set a background pattern image in their profile theme.

Highlights:

• Updated `ProfileTheme` model and schema to include `backgroundPatternImage`.
• Modified `UpdateTheme.tsx` to handle background pattern image upload and display.
• Enhanced `ChooseFile` component to support disabled state during file upload.

Read more: https://pierre.co/hey/hey/yoginth/eng-99-able-to-set-background-pattern-image-for-pro-users
  • Loading branch information
Yoginth authored and Pierre committed Sep 27, 2024
1 parent c6e04e2 commit 015c8ad
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 19 deletions.
2 changes: 2 additions & 0 deletions apps/api/src/routes/profile/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export const get = [

await setRedis(cacheKey, response);
logger.info(`Profile details fetched for ${id}`);

return res.status(200).json({ result: response, success: true });
} catch (error) {
return catchedError(res, error);
}
Expand Down
12 changes: 9 additions & 3 deletions apps/api/src/routes/profile/theme/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import { object, string } from "zod";
type ExtensionRequest = {
overviewFontStyle: string | null;
publicationFontStyle: string | null;
backgroundPatternImage: string | null;
};

const validationSchema = object({
overviewFontStyle: string().optional(),
publicationFontStyle: string().optional()
publicationFontStyle: string().optional(),
backgroundPatternImage: string().optional()
});

export const post = [
Expand All @@ -37,13 +39,17 @@ export const post = [
return invalidBody(res);
}

const { overviewFontStyle, publicationFontStyle } =
const { overviewFontStyle, publicationFontStyle, backgroundPatternImage } =
body as ExtensionRequest;

try {
const identityToken = req.headers["x-identity-token"] as string;
const payload = parseJwt(identityToken);
const dbPayload = { overviewFontStyle, publicationFontStyle };
const dbPayload = {
overviewFontStyle,
publicationFontStyle,
backgroundPatternImage
};

const data = await prisma.profileTheme.upsert({
create: { id: payload.id, ...dbPayload },
Expand Down
47 changes: 45 additions & 2 deletions apps/web/src/components/Profile/UpdateTheme.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import ChooseFile from "@components/Shared/ChooseFile";
import errorToast from "@helpers/errorToast";
import { getAuthApiHeaders } from "@helpers/getAuthApiHeaders";
import profileThemeFonts, { Font } from "@helpers/profileThemeFonts";
import { uploadFileToIPFS } from "@helpers/uploadToIPFS";
import { HEY_API_URL } from "@hey/data/constants";
import camelCaseToReadable from "@hey/helpers/camelCaseToReadable";
import { Button, Select } from "@hey/ui";
import sanitizeDStorageUrl from "@hey/helpers/sanitizeDStorageUrl";
import { Button, Image, Select, Spinner } from "@hey/ui";
import axios from "axios";
import { type FC, useState } from "react";
import { type ChangeEvent, type FC, useState } from "react";
import toast from "react-hot-toast";
import { useProfileThemeStore } from "src/store/non-persisted/useProfileThemeStore";

const UpdateTheme: FC = () => {
const { theme, setTheme } = useProfileThemeStore();
const [updating, setUpdating] = useState(false);

const [uploadingBackgroundPatternImage, setUploadingBackgroundPatternImage] =
useState(false);

const resetTheme = async () => {
setUpdating(true);
try {
Expand Down Expand Up @@ -49,6 +56,23 @@ const UpdateTheme: FC = () => {
}
};

const uploadBackgroundPatternImage = async (
event: ChangeEvent<HTMLInputElement>
) => {
if (event.target.files?.length) {
try {
setUploadingBackgroundPatternImage(true);
const file = event.target.files[0];
const attachment = await uploadFileToIPFS(file);
setTheme({ ...theme, backgroundPatternImage: attachment.uri });
} catch (error) {
errorToast(error);
} finally {
setUploadingBackgroundPatternImage(false);
}
}
};

return (
<div className="space-y-5">
<div>
Expand Down Expand Up @@ -87,6 +111,25 @@ const UpdateTheme: FC = () => {
}))}
/>
</div>
<div>
<div className="label">Background pattern image</div>
<div className="space-y-3">
{theme?.backgroundPatternImage ? (
<Image
alt="Profile picture crop preview"
className="max-w-28 rounded-lg"
src={sanitizeDStorageUrl(theme.backgroundPatternImage)}
/>
) : null}
<div className="flex items-center space-x-3">
<ChooseFile
onChange={uploadBackgroundPatternImage}
disabled={uploadingBackgroundPatternImage}
/>
{uploadingBackgroundPatternImage && <Spinner size="sm" />}
</div>
</div>
</div>
<div className="flex items-center justify-between space-x-3">
<Button
variant="danger"
Expand Down
10 changes: 1 addition & 9 deletions apps/web/src/components/Profile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,7 @@ const ViewProfile: NextPage = () => {
});

useEffect(() => {
const theme = profileDetails?.theme;
if (theme) {
setTheme({
overviewFontStyle: theme.overviewFontStyle,
publicationFontStyle: theme.publicationFontStyle
});
} else {
setTheme(null);
}
setTheme(profileDetails?.theme || null);
}, [profileDetails?.theme]);

if (!isReady || profileLoading) {
Expand Down
4 changes: 3 additions & 1 deletion apps/web/src/components/Shared/ChooseFile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { useId } from "react";

interface ChooseFileProps {
onChange: ChangeEventHandler<HTMLInputElement>;
disabled?: boolean;
}

const ChooseFile: FC<ChooseFileProps> = ({ onChange }) => {
const ChooseFile: FC<ChooseFileProps> = ({ onChange, disabled }) => {
const id = useId();

return (
Expand All @@ -23,6 +24,7 @@ const ChooseFile: FC<ChooseFileProps> = ({ onChange }) => {
className="hidden"
id={id}
onChange={onChange}
disabled={disabled}
onClick={(event) => {
(event.target as HTMLInputElement).value = "";
}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "ProfileTheme" ADD COLUMN "backgroundPatternImage" TEXT;
9 changes: 5 additions & 4 deletions packages/db/prisma/db/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,9 @@ model ProfileStatus {
}

model ProfileTheme {
id String @id
overviewFontStyle String?
publicationFontStyle String?
createdAt DateTime @default(now())
id String @id
overviewFontStyle String?
publicationFontStyle String?
backgroundPatternImage String?
createdAt DateTime @default(now())
}
1 change: 1 addition & 0 deletions packages/types/hey.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export type Preferences = {
export type ProfileTheme = {
overviewFontStyle?: string;
publicationFontStyle?: string;
backgroundPatternImage?: string;
};

export type ProfileDetails = {
Expand Down

0 comments on commit 015c8ad

Please sign in to comment.