From 1c4d79139b4e15d701764d6f8fe84c9e097257de Mon Sep 17 00:00:00 2001 From: palina0k Date: Mon, 10 Feb 2025 10:42:39 -0800 Subject: [PATCH 1/8] Initial Commit --- app/(pages)/_components/MediaSelector/MediaSelector.tsx | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/(pages)/_components/MediaSelector/MediaSelector.tsx diff --git a/app/(pages)/_components/MediaSelector/MediaSelector.tsx b/app/(pages)/_components/MediaSelector/MediaSelector.tsx new file mode 100644 index 0000000..e69de29 From 5a673459d5ee1f3ba870e7d29c6b7ab55255b904 Mon Sep 17 00:00:00 2001 From: brandonw504 Date: Wed, 19 Feb 2025 14:34:15 -0800 Subject: [PATCH 2/8] Removed extra console log --- app/(api)/_datalib/_services/Products.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/(api)/_datalib/_services/Products.ts b/app/(api)/_datalib/_services/Products.ts index 8c5d6a7..9e2aed8 100644 --- a/app/(api)/_datalib/_services/Products.ts +++ b/app/(api)/_datalib/_services/Products.ts @@ -6,7 +6,6 @@ export default class Products { // CREATE static async create(input: ProductInventoryInput) { const { productInput, inventoryInput } = input; - console.log(input); const { name, price, From 84e0b195cb29b46e584a76c5d938bfd1ecb2676e Mon Sep 17 00:00:00 2001 From: hdjekso Date: Sun, 23 Feb 2025 14:49:59 -0800 Subject: [PATCH 3/8] preliminary implementation of MediaSelector --- .../MediaFromGallery.module.scss | 12 +++ .../MediaSelector/MediaFromGallery.tsx | 24 +++++ .../MediaSelector/MediaFromUpload.module.scss | 11 +++ .../MediaSelector/MediaFromUpload.tsx | 83 ++++++++++++++++++ .../MediaSelector/MediaSelector.module.scss | 29 ++++++ .../MediaSelector/MediaSelector.tsx | 41 +++++++++ .../UploadedMediaPopup.module.scss | 64 ++++++++++++++ .../UploadedMediaPopup/UploadedMediaPopup.tsx | 75 ++++++++++++++++ app/(pages)/_contexts/AuthContext.tsx | 56 ++++++++++++ app/(pages)/_contexts/ContentFormContext.tsx | 61 +++++++++++++ .../_contexts/ContentWindowContext.tsx | 11 +++ app/(pages)/_contexts/FilterContext.tsx | 57 ++++++++++++ app/(pages)/_contexts/SelectContext.tsx | 57 ++++++++++++ app/(pages)/_contexts/SidebarContext.tsx | 36 ++++++++ app/(pages)/_hooks/useContentFormContext.ts | 12 +++ app/(pages)/_hooks/useSelectContext.ts | 12 +++ public/content/[content_type]/add.svg | 4 + public/content/[content_type]/check.svg | 3 + public/content/[content_type]/trash.svg | 14 +++ public/content/form/back-button.png | Bin 0 -> 27931 bytes public/content/form/bookmark.png | Bin 0 -> 5835 bytes public/content/form/delete.png | Bin 0 -> 78532 bytes public/content/form/drag-icon.png | Bin 0 -> 92672 bytes public/content/form/upload.png | Bin 0 -> 6831 bytes tsconfig.json | 2 + 25 files changed, 664 insertions(+) create mode 100644 app/(pages)/_components/MediaSelector/MediaFromGallery.module.scss create mode 100644 app/(pages)/_components/MediaSelector/MediaFromGallery.tsx create mode 100644 app/(pages)/_components/MediaSelector/MediaFromUpload.module.scss create mode 100644 app/(pages)/_components/MediaSelector/MediaFromUpload.tsx create mode 100644 app/(pages)/_components/MediaSelector/MediaSelector.module.scss create mode 100644 app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss create mode 100644 app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.tsx create mode 100644 app/(pages)/_contexts/AuthContext.tsx create mode 100644 app/(pages)/_contexts/ContentFormContext.tsx create mode 100644 app/(pages)/_contexts/ContentWindowContext.tsx create mode 100644 app/(pages)/_contexts/FilterContext.tsx create mode 100644 app/(pages)/_contexts/SelectContext.tsx create mode 100644 app/(pages)/_contexts/SidebarContext.tsx create mode 100644 app/(pages)/_hooks/useContentFormContext.ts create mode 100644 app/(pages)/_hooks/useSelectContext.ts create mode 100644 public/content/[content_type]/add.svg create mode 100644 public/content/[content_type]/check.svg create mode 100644 public/content/[content_type]/trash.svg create mode 100644 public/content/form/back-button.png create mode 100644 public/content/form/bookmark.png create mode 100644 public/content/form/delete.png create mode 100644 public/content/form/drag-icon.png create mode 100644 public/content/form/upload.png diff --git a/app/(pages)/_components/MediaSelector/MediaFromGallery.module.scss b/app/(pages)/_components/MediaSelector/MediaFromGallery.module.scss new file mode 100644 index 0000000..f3d8e24 --- /dev/null +++ b/app/(pages)/_components/MediaSelector/MediaFromGallery.module.scss @@ -0,0 +1,12 @@ +.container { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + gap: var(--tiny-spacer); + padding: var(--large-spacer) var(--medium-spacer); + border-radius: var(--b-radius); + background-color: var(--primary-medium); + text-align: center; + cursor: pointer; +} \ No newline at end of file diff --git a/app/(pages)/_components/MediaSelector/MediaFromGallery.tsx b/app/(pages)/_components/MediaSelector/MediaFromGallery.tsx new file mode 100644 index 0000000..585aa5c --- /dev/null +++ b/app/(pages)/_components/MediaSelector/MediaFromGallery.tsx @@ -0,0 +1,24 @@ +'use client'; +import Image from 'next/image'; +import styles from './MediaFromGallery.module.scss'; +import bookmarkIcon from '@public/content/form/bookmark.png'; +import useSelectContext from '@app/(pages)/_hooks/useSelectContext'; +import { Fragment } from 'react'; +import UploadedMediaPopup from '@components/UploadedMediaPopup/UploadedMediaPopup'; + +interface MediaFromGalleryProps { + fieldName: string; +} + +export default function MediaFromGallery({ fieldName }: MediaFromGalleryProps) { + const { toggleSelectMode } = useSelectContext(); + return ( + +
+ bookmark icon +

Choose from Uploaded Media

+
+ +
+ ); +} diff --git a/app/(pages)/_components/MediaSelector/MediaFromUpload.module.scss b/app/(pages)/_components/MediaSelector/MediaFromUpload.module.scss new file mode 100644 index 0000000..e410ceb --- /dev/null +++ b/app/(pages)/_components/MediaSelector/MediaFromUpload.module.scss @@ -0,0 +1,11 @@ +.container { + border: 1px dashed var(--text-dark); + border-radius: var(--b-radius); + padding: var(--large-spacer) var(--medium-spacer); + text-align: center; + cursor: pointer; + + >input { + display: none; + } +} \ No newline at end of file diff --git a/app/(pages)/_components/MediaSelector/MediaFromUpload.tsx b/app/(pages)/_components/MediaSelector/MediaFromUpload.tsx new file mode 100644 index 0000000..c08005b --- /dev/null +++ b/app/(pages)/_components/MediaSelector/MediaFromUpload.tsx @@ -0,0 +1,83 @@ +'use client'; +import { useRef, DragEvent, ChangeEvent } from 'react'; +import Image from 'next/image'; +import styles from './MediaFromUpload.module.scss'; + +import uploadIcon from '@public/content/form/upload.png'; +import uploadMediaItem from '@utils/uploadMediaItem'; + +interface MediaFromUploadProps { + //onInput: (files: FileList) => void; + onInput: (mediaItems: any[]) => void; +} + +export default function MediaFromUpload({ onInput }: MediaFromUploadProps) { + const fileInputRef = useRef(null); + + const handleDrop = async (e: DragEvent) => { + e.preventDefault(); + const droppedFiles = e.dataTransfer.files; + //onInput(droppedFiles); + await processFiles(droppedFiles); + }; + + const handleFileChange = async (e: ChangeEvent) => { + const inputFiles = e.target.files; + //onInput(inputFiles ?? new FileList()); + if (inputFiles) { + await processFiles(inputFiles); + } + e.target.value = ''; + }; + + //new function + const processFiles = async (files: FileList) => { + const uploadedMediaItems = []; + + for (const file of Array.from(files)) { + const mediaItem = { + type: file.type.startsWith('video') ? 'video' : 'image', + src: URL.createObjectURL(file), // Temporary preview URL + }; + + const response = await uploadMediaItem(mediaItem); //call backend function + if (response.ok) { + uploadedMediaItems.push(response.body); + } + } + + onInput(uploadedMediaItems); // Calls the function with new media items + }; + + + const handleDragOver = (e: DragEvent) => { + e.preventDefault(); + }; + + const handleUploadClick = () => { + if (fileInputRef.current) { + fileInputRef.current.click(); + } + }; + + return ( +
+ upload icon +

+ Upload a File or Drag and Drop +

+ +
+ ); +} diff --git a/app/(pages)/_components/MediaSelector/MediaSelector.module.scss b/app/(pages)/_components/MediaSelector/MediaSelector.module.scss new file mode 100644 index 0000000..050358b --- /dev/null +++ b/app/(pages)/_components/MediaSelector/MediaSelector.module.scss @@ -0,0 +1,29 @@ +@use 'media'; + +.container { + display: grid; + grid-template-columns: 1fr auto 1fr; + gap: var(--small-spacer); + h4 { + font-weight: 400; + } +} + +.or_container{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: var(--tiny-spacer); + @include media.tablet { + flex-direction: row; + } +} + +.line { + border-left: 1px solid var(--text-dark); + height: 25px; + @include media.tablet { + display: none; + } +} \ No newline at end of file diff --git a/app/(pages)/_components/MediaSelector/MediaSelector.tsx b/app/(pages)/_components/MediaSelector/MediaSelector.tsx index e69de29..3640a90 100644 --- a/app/(pages)/_components/MediaSelector/MediaSelector.tsx +++ b/app/(pages)/_components/MediaSelector/MediaSelector.tsx @@ -0,0 +1,41 @@ +'use client'; +import styles from './MediaSelector.module.scss'; +import MediaFromGallery from './MediaFromGallery'; +import MediaFromUpload from './MediaFromUpload'; +import useContentFormContext from '@hooks/useContentFormContext'; +import convertFileToMediaItem from '../../_utils/convertFileToMediaItem'; +import SelectContextProvider from '@app/(pages)/_contexts/SelectContext'; + +interface MediaSelectorProps { + field_name: string; +} + +export default function MediaSelector({ field_name }: MediaSelectorProps) { + const { data, updateField } = useContentFormContext(); + + /*const onInput = (files: FileList) => { + const updatedFieldValue = [ + ...data[field_name], + ...Array.from(files).map(convertFileToMediaItem), + ]; + updateField(field_name, updatedFieldValue); + };*/ + const onInput = (uploadedMediaItems: any[]) => { //files are already processed, not in raw format + const updatedFieldValue = [...data[field_name], ...uploadedMediaItems]; + updateField(field_name, updatedFieldValue); + }; + + return ( +
+ +
+
+

or

+
+
+ + + +
+ ); +} \ No newline at end of file diff --git a/app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss b/app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss new file mode 100644 index 0000000..377c5c8 --- /dev/null +++ b/app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss @@ -0,0 +1,64 @@ +.container { + position: fixed; + display: flex; + flex-direction: column; + display: none; + background-color: var(--background-primary); + overflow-y: scroll; + padding-bottom: var(--enormous-spacer); + + &.visible { + display: flex; + } +} + +.header { + display: flex; + flex-direction: column; + padding: 0 var(--medium-spacer); + gap: var(--spacer); + + .title { + font-size: 3rem; + font-weight: 700; + } +} + +.data_container { + display: flex; + flex-direction: column; + margin: var(--medium-spacer) 0; + gap: var(--medium-spacer); +} + +.button_container { + display: flex; + flex-direction: row; + gap: var(--spacer); + justify-content: center; + margin-top: var(--medium-spacer); + + .attach, .exit_button { + border-radius: 8px; + box-shadow: 0px 4px 35px 0px rgba(60, 37, 126, 0.40); + display: flex; + padding: 20px 36px; + justify-content: center; + align-items: center; + color: #FFF; + font-family: var(--font-dm-sans); + font-size: 1.5rem; + font-weight: 500; + color: var(--text-light); + } + + .attach { + background: var(--primary); + width: 480px; + } + + .exit_button { + background: var(--red); + padding: 20px 58px; + } +} \ No newline at end of file diff --git a/app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.tsx b/app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.tsx new file mode 100644 index 0000000..c385095 --- /dev/null +++ b/app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.tsx @@ -0,0 +1,75 @@ +'use client'; +import styles from './UploadedMediaPopup.module.scss'; +import useSelectContext from '@app/(pages)/_hooks/useSelectContext'; +import FilterContextProvider from '@app/(pages)/_contexts/FilterContext'; +import MediaCard from '../MediaCard/MediaCard'; +import useMedia from '@app/(pages)/_hooks/useMedia'; +import MediaItem from '@app/_types/media/MediaItem'; +import ContentSection from '@components/ContentSection/ContentSection'; +import ContentFilters from '@components/ContentFilters/ContentFilters'; +import useContentFormContext from '@app/(pages)/_hooks/useContentFormContext'; +import useContentWindowContext from '@hooks/useContentWindowContext'; + +interface UploadedMediaPopupProps { + fieldName: string; +} + +export default function UploadedMediaPopup({ + fieldName, +}: UploadedMediaPopupProps) { + const { top, left, bottom, right } = useContentWindowContext(); + const position = { + top: `${top}px`, + left: `${left}px`, + bottom: `${window.innerHeight - bottom}px`, + right: `${window.innerWidth - right}px`, + }; + + const { selectMode, toggleSelectMode, selectedIds } = useSelectContext(); + const { loading, data: mediaData, error } = useMedia(); + const { updateField, data } = useContentFormContext(); + + if (loading) { + return 'loading...'; + } + + if (error) { + return error; + } + + const data_list = mediaData.map((mediaItem: MediaItem) => { + return ; + }); + + const attachMedia = () => { + const selectedMedia = Object.values(selectedIds).filter(Boolean); + const updatedFieldValue = [...data[fieldName], ...selectedMedia]; + updateField(fieldName, updatedFieldValue); + toggleSelectMode(); + }; + + return ( +
+ +
+
+

Uploaded Media

+ +
+ {data_list} +
+
+
+ + +
+
+ ); +} diff --git a/app/(pages)/_contexts/AuthContext.tsx b/app/(pages)/_contexts/AuthContext.tsx new file mode 100644 index 0000000..5f7a00e --- /dev/null +++ b/app/(pages)/_contexts/AuthContext.tsx @@ -0,0 +1,56 @@ +'use client'; +import { createContext, useState, useEffect, useCallback } from 'react'; +import VerifyAuthToken from '@actions/auth/verifyAuthToken'; +import { AuthToken } from '@app/_types/auth/AuthToken'; +import Logout from '@actions/auth/logout'; + +interface AuthProviderValue { + user: AuthToken; + loading: boolean; + login: (user: AuthToken) => void; + logout: () => void; +} + +export type { AuthProviderValue }; + +export const AuthContext = createContext({}); + +export function AuthContextProvider({ + children, +}: { + children: React.ReactNode; +}) { + const [user, setUser] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + const updateAuth = async () => { + const data = await VerifyAuthToken(); + if (!data.ok) { + setLoading(false); + return; + } + const userData = data.body as AuthToken; + + setUser(userData); + setLoading(false); + }; + + updateAuth(); + }, []); + + const login = useCallback((user: AuthToken | null) => { + setUser(user); + }, []); + + const logout = useCallback(() => { + Logout(); + setUser(null); + }, []); + + const contextValue = { user, loading, login, logout }; + + return ( + {children} + ); +} diff --git a/app/(pages)/_contexts/ContentFormContext.tsx b/app/(pages)/_contexts/ContentFormContext.tsx new file mode 100644 index 0000000..b424a6b --- /dev/null +++ b/app/(pages)/_contexts/ContentFormContext.tsx @@ -0,0 +1,61 @@ +'use client'; +import { useState, createContext } from 'react'; + +interface ContentFormContextValue { + content_type: string; + id: string | null; + data: { [key: string]: any }; + updateField: (field_name: string, value: any) => void; + setData: (value: any) => void; + setId: (value: string) => void; +} + +export type { ContentFormContextValue }; + +export const ContentFormContext = createContext({ + content_type: '', + id: null, + data: {}, + updateField: (_, __) => {}, + setData: (_) => {}, + setId: (_) => {}, +}); + +interface ContentFormContextProviderProps { + content_type: string; + id?: string | null; + initialValue?: object; + children: React.ReactNode; +} + +export default function ContentFormContextProvider({ + content_type, + id = null, + initialValue = {}, + children, +}: ContentFormContextProviderProps) { + const [data, setData] = useState(initialValue); + const [idVar, setId] = useState(id); + + const updateField = (field_name: string, value: any) => { + setData((prev) => ({ + ...prev, + [field_name]: value, + })); + }; + + const value = { + content_type, + id: idVar, + data, + updateField, + setData, + setId, + }; + + return ( + + {children} + + ); +} diff --git a/app/(pages)/_contexts/ContentWindowContext.tsx b/app/(pages)/_contexts/ContentWindowContext.tsx new file mode 100644 index 0000000..9ba3dc3 --- /dev/null +++ b/app/(pages)/_contexts/ContentWindowContext.tsx @@ -0,0 +1,11 @@ +import { createContext, createRef } from 'react'; + +interface ContentWindowContextProviderValue { + contentWindowRef: React.Ref | null; +} + +export type { ContentWindowContextProviderValue }; + +export const ContentWindowContext = createContext({ + contentWindowRef: createRef(), +}); diff --git a/app/(pages)/_contexts/FilterContext.tsx b/app/(pages)/_contexts/FilterContext.tsx new file mode 100644 index 0000000..f147c34 --- /dev/null +++ b/app/(pages)/_contexts/FilterContext.tsx @@ -0,0 +1,57 @@ +'use client'; +import { createContext, useState, useCallback } from 'react'; + +interface FilterContextValue { + filters: string[]; + search: string; + setSearch: React.Dispatch>; + setFilters: React.Dispatch>; + applyFilters: (_: object[]) => object[]; +} + +export type { FilterContextValue }; + +export const FilterContext = createContext({ + filters: [], + search: '', + setSearch: () => {}, + setFilters: () => {}, + applyFilters: (_: object[]) => [], +}); + +export default function FilterContextProvider({ + children, +}: { + children: React.ReactNode; +}) { + const [filters, setFilters] = useState([]); + const [search, setSearch] = useState(''); + + const applyFilters = useCallback( + (data: object[]) => { + const hasValueContaining = (obj: any, searchStr: string): any => { + const values = Object.values(obj); + if (typeof obj === 'string') { + return obj.toLowerCase().includes(searchStr.toLowerCase()); + } + + return values.some((value: any) => + hasValueContaining(value, searchStr) + ); + }; + return data.filter((item) => hasValueContaining(item, search)); + }, + [search] + ); + + const value = { + filters, + search, + setFilters, + setSearch, + applyFilters, + }; + return ( + {children} + ); +} diff --git a/app/(pages)/_contexts/SelectContext.tsx b/app/(pages)/_contexts/SelectContext.tsx new file mode 100644 index 0000000..28e1b55 --- /dev/null +++ b/app/(pages)/_contexts/SelectContext.tsx @@ -0,0 +1,57 @@ +'use client'; +import { createContext, useState, useCallback } from 'react'; + +interface SelectContextValue { + selectMode: boolean; + toggleSelectMode: () => void; + selectedIds: { [key: string]: any }; + toggleId: (id: string, data?: any) => void; + resetSelectedIds: () => void; +} + +export type { SelectContextValue }; + +export const SelectContext = createContext({ + selectMode: true, + toggleSelectMode: () => {}, + selectedIds: {}, + toggleId: (_: string, __: any) => {}, + resetSelectedIds: () => {}, +}); + +export default function SelectContextProvider({ + children, +}: { + children: React.ReactNode; +}) { + const [selectMode, setSelectMode] = useState(false); + const [selectedIds, setSelectedIds] = useState<{ [key: string]: boolean }>( + {} + ); + const toggleSelectMode = useCallback(() => { + setSelectMode((prev) => !prev); + setSelectedIds({}); + }, [setSelectMode]); + + const resetSelectedIds = () => { + setSelectedIds({}); + }; + + const toggleId = (id: string, data: any = null) => { + setSelectedIds({ + ...selectedIds, + [id]: selectedIds?.[id] ? null : data || true, + }); + }; + + const value = { + selectMode, + toggleSelectMode, + selectedIds, + toggleId, + resetSelectedIds, + }; + return ( + {children} + ); +} diff --git a/app/(pages)/_contexts/SidebarContext.tsx b/app/(pages)/_contexts/SidebarContext.tsx new file mode 100644 index 0000000..7e75272 --- /dev/null +++ b/app/(pages)/_contexts/SidebarContext.tsx @@ -0,0 +1,36 @@ +'use client'; +import { usePathname } from 'next/navigation'; +import { createContext, useEffect, useState } from 'react'; + +interface SidebarContextValue { + activeLink: string; + setActiveLink: React.Dispatch>; +} + +export type { SidebarContextValue }; + +export const SidebarContext = createContext({ + activeLink: '', + setActiveLink: () => {}, +}); + +export default function SidebarContextProvider({ + children, +}: { + children: React.ReactNode; +}) { + const pathname = usePathname(); + const [activeLink, setActiveLink] = useState(pathname); + + useEffect(() => { + setActiveLink(pathname); + }, [pathname]); + + const value = { + activeLink, + setActiveLink, + }; + return ( + {children} + ); +} diff --git a/app/(pages)/_hooks/useContentFormContext.ts b/app/(pages)/_hooks/useContentFormContext.ts new file mode 100644 index 0000000..1313134 --- /dev/null +++ b/app/(pages)/_hooks/useContentFormContext.ts @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { ContentFormContext } from '@contexts/ContentFormContext'; + +export default function useContentFormContext() { + const context = useContext(ContentFormContext); + if (!context) { + throw new Error( + 'useContentFormContext must be used within an ContentFormContextProvider' + ); + } + return context; +} diff --git a/app/(pages)/_hooks/useSelectContext.ts b/app/(pages)/_hooks/useSelectContext.ts new file mode 100644 index 0000000..5cd45db --- /dev/null +++ b/app/(pages)/_hooks/useSelectContext.ts @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { SelectContext } from '@contexts/SelectContext'; + +export default function useSelectContext() { + const context = useContext(SelectContext); + if (!context) { + throw new Error( + 'useSelectContext must be used within an SelectContextProvider' + ); + } + return context; +} diff --git a/public/content/[content_type]/add.svg b/public/content/[content_type]/add.svg new file mode 100644 index 0000000..513f0d0 --- /dev/null +++ b/public/content/[content_type]/add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/public/content/[content_type]/check.svg b/public/content/[content_type]/check.svg new file mode 100644 index 0000000..83cde5e --- /dev/null +++ b/public/content/[content_type]/check.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/public/content/[content_type]/trash.svg b/public/content/[content_type]/trash.svg new file mode 100644 index 0000000..0f352cf --- /dev/null +++ b/public/content/[content_type]/trash.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/public/content/form/back-button.png b/public/content/form/back-button.png new file mode 100644 index 0000000000000000000000000000000000000000..083c87070017873f7f4b2806194090cbdafe0ba1 GIT binary patch literal 27931 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Ξ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 literal 0 HcmV?d00001 diff --git a/public/content/form/bookmark.png b/public/content/form/bookmark.png new file mode 100644 index 0000000000000000000000000000000000000000..2bc40d46efbf79ff4916b70cc4223e1eb56dec81 GIT binary patch literal 5835 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 Zd*#^SU4Om)`2*ysi1(x46CQ#u{2v4ZwEO@7 literal 0 HcmV?d00001 diff --git a/public/content/form/drag-icon.png b/public/content/form/drag-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b697554d1ad4988f230a3fcc2fd2bae8ae8a2e9c GIT binary patch literal 92672 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

gH|k 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 JBRK@z{V&ygW+MOq literal 0 HcmV?d00001 diff --git a/tsconfig.json b/tsconfig.json index 527c9c5..c6c525a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,8 @@ } ], "paths": { + "@app/*": ["./app/*"], + "@public/*": ["./public/*"], "@globals/*": ["./app/(pages)/_globals/*"], "@components/*": ["./app/(pages)/_components/*"], "@data/*": ["./app/(pages)/_data/*"], From 0f4c2dbebb73c5efe191c3c47e8f174f65e3a188 Mon Sep 17 00:00:00 2001 From: palina0k Date: Wed, 26 Feb 2025 21:27:32 -0800 Subject: [PATCH 4/8] Relocated the components to a page, uploaded-media. --- .../MediaFromGallery.module.scss | 12 -- .../MediaSelector/MediaFromGallery.tsx | 24 --- app/(pages)/_contexts/AuthContext.tsx | 56 ------- app/(pages)/_contexts/SidebarContext.tsx | 36 ----- app/(pages)/_hooks/useMedia.ts | 23 +++ app/(pages)/_hooks/useUploadMedia.ts | 5 + app/(pages)/_types/media/MediaItem.ts | 17 +++ app/(pages)/_utils/convertFileToMediaItem.ts | 15 ++ app/(pages)/_utils/uploadMediaItem.ts | 76 ++++++++++ .../_components/MediaCard/ImagePreview.tsx | 18 +++ .../MediaCard/MediaCard.module.scss | 67 +++++++++ .../_components/MediaCard/MediaCard.tsx | 50 +++++++ .../MediaHeader/MediaHeader.module.scss | 78 ++++++++++ .../_components/MediaHeader/MediaHeader.tsx | 61 ++++++++ .../MediaItemField/MediaItemField.module.scss | 0 .../MediaItemField/MediaItemField.tsx | 13 ++ .../MediaListField/MediaList.module.scss | 96 ++++++++++++ .../_components/MediaListField/MediaList.tsx | 139 ++++++++++++++++++ .../MediaListField/MediaListField.module.scss | 5 + .../MediaListField/MediaListField.tsx | 21 +++ .../MediaSelector/MediaFromUpload.module.scss | 0 .../MediaSelector/MediaFromUpload.tsx | 0 .../MediaSelector/MediaSelector.module.scss | 0 .../MediaSelector/MediaSelector.tsx | 1 - .../UploadedMediaPopup.module.scss | 0 .../UploadedMediaPopup/UploadedMediaPopup.tsx | 8 - app/(pages)/uploaded-media/page.module.scss | 8 + app/(pages)/uploaded-media/page.tsx | 32 ++++ tsconfig.json | 1 + 29 files changed, 725 insertions(+), 137 deletions(-) delete mode 100644 app/(pages)/_components/MediaSelector/MediaFromGallery.module.scss delete mode 100644 app/(pages)/_components/MediaSelector/MediaFromGallery.tsx delete mode 100644 app/(pages)/_contexts/AuthContext.tsx delete mode 100644 app/(pages)/_contexts/SidebarContext.tsx create mode 100644 app/(pages)/_hooks/useMedia.ts create mode 100644 app/(pages)/_hooks/useUploadMedia.ts create mode 100644 app/(pages)/_types/media/MediaItem.ts create mode 100644 app/(pages)/_utils/convertFileToMediaItem.ts create mode 100644 app/(pages)/_utils/uploadMediaItem.ts create mode 100644 app/(pages)/uploaded-media/_components/MediaCard/ImagePreview.tsx create mode 100644 app/(pages)/uploaded-media/_components/MediaCard/MediaCard.module.scss create mode 100644 app/(pages)/uploaded-media/_components/MediaCard/MediaCard.tsx create mode 100644 app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.module.scss create mode 100644 app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.tsx create mode 100644 app/(pages)/uploaded-media/_components/MediaItemField/MediaItemField.module.scss create mode 100644 app/(pages)/uploaded-media/_components/MediaItemField/MediaItemField.tsx create mode 100644 app/(pages)/uploaded-media/_components/MediaListField/MediaList.module.scss create mode 100644 app/(pages)/uploaded-media/_components/MediaListField/MediaList.tsx create mode 100644 app/(pages)/uploaded-media/_components/MediaListField/MediaListField.module.scss create mode 100644 app/(pages)/uploaded-media/_components/MediaListField/MediaListField.tsx rename app/(pages)/{ => uploaded-media}/_components/MediaSelector/MediaFromUpload.module.scss (100%) rename app/(pages)/{ => uploaded-media}/_components/MediaSelector/MediaFromUpload.tsx (100%) rename app/(pages)/{ => uploaded-media}/_components/MediaSelector/MediaSelector.module.scss (100%) rename app/(pages)/{ => uploaded-media}/_components/MediaSelector/MediaSelector.tsx (96%) rename app/(pages)/{ => uploaded-media}/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss (100%) rename app/(pages)/{ => uploaded-media}/_components/UploadedMediaPopup/UploadedMediaPopup.tsx (77%) create mode 100644 app/(pages)/uploaded-media/page.module.scss create mode 100644 app/(pages)/uploaded-media/page.tsx diff --git a/app/(pages)/_components/MediaSelector/MediaFromGallery.module.scss b/app/(pages)/_components/MediaSelector/MediaFromGallery.module.scss deleted file mode 100644 index f3d8e24..0000000 --- a/app/(pages)/_components/MediaSelector/MediaFromGallery.module.scss +++ /dev/null @@ -1,12 +0,0 @@ -.container { - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - gap: var(--tiny-spacer); - padding: var(--large-spacer) var(--medium-spacer); - border-radius: var(--b-radius); - background-color: var(--primary-medium); - text-align: center; - cursor: pointer; -} \ No newline at end of file diff --git a/app/(pages)/_components/MediaSelector/MediaFromGallery.tsx b/app/(pages)/_components/MediaSelector/MediaFromGallery.tsx deleted file mode 100644 index 585aa5c..0000000 --- a/app/(pages)/_components/MediaSelector/MediaFromGallery.tsx +++ /dev/null @@ -1,24 +0,0 @@ -'use client'; -import Image from 'next/image'; -import styles from './MediaFromGallery.module.scss'; -import bookmarkIcon from '@public/content/form/bookmark.png'; -import useSelectContext from '@app/(pages)/_hooks/useSelectContext'; -import { Fragment } from 'react'; -import UploadedMediaPopup from '@components/UploadedMediaPopup/UploadedMediaPopup'; - -interface MediaFromGalleryProps { - fieldName: string; -} - -export default function MediaFromGallery({ fieldName }: MediaFromGalleryProps) { - const { toggleSelectMode } = useSelectContext(); - return ( - -

- bookmark icon -

Choose from Uploaded Media

-
- - - ); -} diff --git a/app/(pages)/_contexts/AuthContext.tsx b/app/(pages)/_contexts/AuthContext.tsx deleted file mode 100644 index 5f7a00e..0000000 --- a/app/(pages)/_contexts/AuthContext.tsx +++ /dev/null @@ -1,56 +0,0 @@ -'use client'; -import { createContext, useState, useEffect, useCallback } from 'react'; -import VerifyAuthToken from '@actions/auth/verifyAuthToken'; -import { AuthToken } from '@app/_types/auth/AuthToken'; -import Logout from '@actions/auth/logout'; - -interface AuthProviderValue { - user: AuthToken; - loading: boolean; - login: (user: AuthToken) => void; - logout: () => void; -} - -export type { AuthProviderValue }; - -export const AuthContext = createContext({}); - -export function AuthContextProvider({ - children, -}: { - children: React.ReactNode; -}) { - const [user, setUser] = useState(null); - const [loading, setLoading] = useState(true); - - useEffect(() => { - const updateAuth = async () => { - const data = await VerifyAuthToken(); - if (!data.ok) { - setLoading(false); - return; - } - const userData = data.body as AuthToken; - - setUser(userData); - setLoading(false); - }; - - updateAuth(); - }, []); - - const login = useCallback((user: AuthToken | null) => { - setUser(user); - }, []); - - const logout = useCallback(() => { - Logout(); - setUser(null); - }, []); - - const contextValue = { user, loading, login, logout }; - - return ( - {children} - ); -} diff --git a/app/(pages)/_contexts/SidebarContext.tsx b/app/(pages)/_contexts/SidebarContext.tsx deleted file mode 100644 index 7e75272..0000000 --- a/app/(pages)/_contexts/SidebarContext.tsx +++ /dev/null @@ -1,36 +0,0 @@ -'use client'; -import { usePathname } from 'next/navigation'; -import { createContext, useEffect, useState } from 'react'; - -interface SidebarContextValue { - activeLink: string; - setActiveLink: React.Dispatch>; -} - -export type { SidebarContextValue }; - -export const SidebarContext = createContext({ - activeLink: '', - setActiveLink: () => {}, -}); - -export default function SidebarContextProvider({ - children, -}: { - children: React.ReactNode; -}) { - const pathname = usePathname(); - const [activeLink, setActiveLink] = useState(pathname); - - useEffect(() => { - setActiveLink(pathname); - }, [pathname]); - - const value = { - activeLink, - setActiveLink, - }; - return ( - {children} - ); -} diff --git a/app/(pages)/_hooks/useMedia.ts b/app/(pages)/_hooks/useMedia.ts new file mode 100644 index 0000000..1e903da --- /dev/null +++ b/app/(pages)/_hooks/useMedia.ts @@ -0,0 +1,23 @@ +import MediaItem from '@app/_types/media/MediaItem'; +import { useState, useEffect } from 'react'; +import { FindMediaItems } from '@app/(api)/_actions/media/findMediaItem'; + +export default function useMedia() { + const [loading, setLoading] = useState(true); + const [data, setData] = useState([]); + const [error, setError] = useState(''); + useEffect(() => { + const fetchMedia = async () => { + const res = await FindMediaItems(); + if (res.ok) { + setData(res.body); + } else { + setError(res.error || ''); + } + setLoading(false); + }; + fetchMedia(); + }, []); + + return { loading, data, error }; +} diff --git a/app/(pages)/_hooks/useUploadMedia.ts b/app/(pages)/_hooks/useUploadMedia.ts new file mode 100644 index 0000000..1d9c53b --- /dev/null +++ b/app/(pages)/_hooks/useUploadMedia.ts @@ -0,0 +1,5 @@ +import MediaItem from '@typeDefs/media/MediaItem'; + +export default function useUploadMedia(data: MediaItem) { + return data; +} \ No newline at end of file diff --git a/app/(pages)/_types/media/MediaItem.ts b/app/(pages)/_types/media/MediaItem.ts new file mode 100644 index 0000000..f499bae --- /dev/null +++ b/app/(pages)/_types/media/MediaItem.ts @@ -0,0 +1,17 @@ +interface MediaItem { + _id: string | null; + cloudinary_id: string | null; + name: string; + type: string; + format: string; + src: string; + alt?: string; + size: number; + width: number | null; + height: number | null; + _created_at?: string | null; + _last_modified?: string | null; + } + + export default MediaItem; + \ No newline at end of file diff --git a/app/(pages)/_utils/convertFileToMediaItem.ts b/app/(pages)/_utils/convertFileToMediaItem.ts new file mode 100644 index 0000000..fd9f1c8 --- /dev/null +++ b/app/(pages)/_utils/convertFileToMediaItem.ts @@ -0,0 +1,15 @@ +import MediaItem from '@typeDefs/media/MediaItem'; +export default function convertFileToMediaItem(file: File): MediaItem { + const [fileType, fileFormat] = file.type.split('/'); + return { + _id: null, + cloudinary_id: null, + name: file.name, + type: fileType, + format: fileFormat, + src: URL.createObjectURL(file), + size: file.size, + width: null, + height: null, + }; +} diff --git a/app/(pages)/_utils/uploadMediaItem.ts b/app/(pages)/_utils/uploadMediaItem.ts new file mode 100644 index 0000000..26a1e4f --- /dev/null +++ b/app/(pages)/_utils/uploadMediaItem.ts @@ -0,0 +1,76 @@ +import GenerateCloudinarySignature from '@actions/cloudinary/generateCloudinarySignature'; +import { CreateMediaItem } from '@actions/media/createMediaItem'; +import HttpError from '@utils/response/HttpError'; +import MediaItem from '@typeDefs/media/MediaItem'; +import DeleteCloudinaryObject from '@actions/cloudinary/deleteCloudinaryItem'; + +export default async function uploadMediaItem(mediaItem: MediaItem) { + try { + const cloudinaryType = getCloudinaryType(mediaItem.type); + const fileRes = await fetch(mediaItem.src); + const file = await fileRes.blob(); + + const requestParams = {}; + const signatureRes = await GenerateCloudinarySignature(requestParams); + if (!signatureRes.ok) { + throw new HttpError(signatureRes.error || 'Internal Server Error'); + } + + const uploadBody = new FormData(); + Object.entries(signatureRes.body?.requestParams || {}).forEach( + ([key, value]) => { + uploadBody.append(key, (value || '').toString()); + } + ); + + uploadBody.append('file', file); + const uploadRes = await fetch( + `${signatureRes.body?.cloudUrl}/${cloudinaryType}/upload`, + { + method: 'POST', + body: uploadBody, + } + ); + + const uploadData = await uploadRes.json(); + + if (uploadData.error) { + throw new HttpError(uploadData.error.message); + } + + const updatedMediaItem = { + ...mediaItem, + cloudinary_id: uploadData.public_id, + src: uploadData.secure_url, + height: uploadData.height || null, + width: uploadData.width || null, + }; + + const { _id: _, ...creationBody } = updatedMediaItem; + + const creationRes = await CreateMediaItem(creationBody); + if (!creationRes.ok) { + const deleteStatus = await DeleteCloudinaryObject( + updatedMediaItem.cloudinary_id, + getCloudinaryType(updatedMediaItem.type) + ); + const errorMsg = `${creationRes.error}${ + deleteStatus.ok ? '' : `\n${deleteStatus.error}` + }`; + throw new Error(errorMsg); + } + + return creationRes; + } catch (e) { + const err = e as HttpError; + return { ok: false, body: null, error: err.message }; + } +} + +function getCloudinaryType(type: string) { + if (type === 'video') { + return type; + } else { + return 'image'; + } +} \ No newline at end of file diff --git a/app/(pages)/uploaded-media/_components/MediaCard/ImagePreview.tsx b/app/(pages)/uploaded-media/_components/MediaCard/ImagePreview.tsx new file mode 100644 index 0000000..e5f06ce --- /dev/null +++ b/app/(pages)/uploaded-media/_components/MediaCard/ImagePreview.tsx @@ -0,0 +1,18 @@ +import Image from 'next/image'; + +interface ImagePreviewProps { + src: string; + alt: string; +} + +export default function ImagePreview({ src, alt }: ImagePreviewProps) { + return ( + {alt} + ); +} diff --git a/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.module.scss b/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.module.scss new file mode 100644 index 0000000..805b681 --- /dev/null +++ b/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.module.scss @@ -0,0 +1,67 @@ +.container { + display: flex; + flex-direction: column; + padding: var(--spacer); + gap: var(--small-spacer); + text-align: left; + border-radius: var(--c-radius); + box-shadow: var(--b-shadow); + background-color: var(--background-light); + + min-width: 324px; + width: calc(calc(100% - 5 * var(--medium-spacer)) / 3); + max-width: 424px; + height: min-content; + cursor: pointer; +} + +.top_row { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--small-spacer); + + h2 { + font-size: 1.5rem; + font-weight: 400; + overflow: hidden; + text-overflow: ellipsis; + text-wrap: nowrap; + } + + .checkbox_container { + height: 1.5rem; + aspect-ratio: 1; + border-radius: 4px; + border: solid 1px black; + overflow: hidden; + flex-shrink: 0; + + .checkbox_internals { + position: relative; + background-color: var(--primary); + display: flex; + height: 100%; + width: 100%; + } + } +} + +.last_edited { + font-size: 0.875rem; + color: var(--text-dark-gray); +} + +.kebab_button { + .kebab { + font-size: 1.5rem; + } +} + +.media_container { + width: 100%; + aspect-ratio: 1.52; + position: relative; + overflow: hidden; + border-radius: var(--b-radius); +} diff --git a/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.tsx b/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.tsx new file mode 100644 index 0000000..7ad54be --- /dev/null +++ b/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.tsx @@ -0,0 +1,50 @@ +'use client'; +import styles from './MediaCard.module.scss'; +import ImagePreview from './ImagePreview'; +import MediaItem from '@typeDefs/media/MediaItem'; +import useSelectContext from '@hooks/useSelectContext'; +import checkMark from '@public/content/[content_type]/check.svg'; +import Image from 'next/image'; + +interface Props { + mediaItem: MediaItem; +} + +export default function MediaCard({ mediaItem }: Props) { + const { src, alt, type, name, format } = mediaItem; + const { selectedIds, toggleId, selectMode } = useSelectContext(); + + const preview = (() => { + switch (type) { + case 'image': + return ; + default: + return format === 'pdf' ? ( + + ) : ( +
{`No preview for media type: ${type}`}
+ ); + } + })(); + + return ( +
toggleId(mediaItem._id || '', mediaItem)} + > +
+ {selectMode && ( +
+ {selectedIds[mediaItem._id || ''] && ( +
+ checkmark +
+ )} +
+ )} +

{name}

+
+
{preview}
+
+ ); +} \ No newline at end of file diff --git a/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.module.scss b/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.module.scss new file mode 100644 index 0000000..7abc3e5 --- /dev/null +++ b/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.module.scss @@ -0,0 +1,78 @@ +.container { + display: flex; + flex-direction: column; + gap: var(--spacer); + padding: 0 var(--medium-spacer); + + >div { + display: flex; + flex-direction: row; + } +} + +.top_row { + justify-content: space-between; + align-items: center; + >h1 { + font-size: 3rem; + font-weight: 700; + } + + .top_right { + display: flex; + flex-direction: row; + gap: var(--small-spacer); + } +} + +.bot_row { + display: flex; + flex-direction: row; + gap: var(--small-spacer); +} + +.select_button_container { + display: flex; + flex-direction: row; + gap: var(--spacer); + align-items: center; + padding: var(--small-spacer) var(--spacer); + background-color: var(--background-light); + border-radius: var(--b-radius); + box-shadow: var(-b-shadow); + + .select_button_icon { + height: 24px; + aspect-ratio: 1; + border-radius: 4px; + border: solid 1px black; + } + + >p { + color: var(--primary); + font-size: 1.375rem; + font-weight: 500; + } +} + +.trash_button_container { + padding: var(--small-spacer) var(--spacer); + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: var(--tiny-spacer); + background-color: var(--red); + border-radius: var(--b-radius); + + > h4 { + font-size: 1.375rem; + font-weight: 500; + color: var(--text-light); + } + + .trash_button_trash_icon { + height: 100%; + width: auto; + } +} \ No newline at end of file diff --git a/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.tsx b/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.tsx new file mode 100644 index 0000000..835a717 --- /dev/null +++ b/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.tsx @@ -0,0 +1,61 @@ +'use client'; +import useSelectContext from '@hooks/useSelectContext'; +import Image from 'next/image'; +//import { DeleteMediaItem } from '@actions/media/deleteMediaItem'; +import styles from './MediaHeader.module.scss'; + +import trash from '@public/content/[content_type]/trash.svg'; + +export default function MediaHeader() { + const { selectMode, toggleSelectMode, selectedIds } = useSelectContext(); + + // const handleTrash = async () => { + // const deleteIds = Object.entries(selectedIds) + // .map(([id, toDelete]) => (toDelete && id) as string) + // .filter(Boolean); + + // if (deleteIds.length === 0) { + // alert('No items selected to trash'); + // } + + // const res = await Promise.all(deleteIds.map((id) => DeleteMediaItem(id))); + + // const ok = res.every(({ ok }) => ok); + // if (ok) { + // alert('Everything worked!'); + // toggleSelectMode(); + // } else { + // alert('Something went wrong!'); + // } + // }; + + return ( +
+
+

Uploaded Media

+
+ + {/* {selectMode && ( + + )} */} +
+
+
+ ); +} diff --git a/app/(pages)/uploaded-media/_components/MediaItemField/MediaItemField.module.scss b/app/(pages)/uploaded-media/_components/MediaItemField/MediaItemField.module.scss new file mode 100644 index 0000000..e69de29 diff --git a/app/(pages)/uploaded-media/_components/MediaItemField/MediaItemField.tsx b/app/(pages)/uploaded-media/_components/MediaItemField/MediaItemField.tsx new file mode 100644 index 0000000..0362f23 --- /dev/null +++ b/app/(pages)/uploaded-media/_components/MediaItemField/MediaItemField.tsx @@ -0,0 +1,13 @@ +import styles from './MediaItemField.module.scss'; + +interface MediaItemFieldProps { + name: string; + initial_value?: any; +} + +export default function MediaItemField({ + name: _, + initial_value: __, +}: MediaItemFieldProps) { + return
MediaItemField
; +} \ No newline at end of file diff --git a/app/(pages)/uploaded-media/_components/MediaListField/MediaList.module.scss b/app/(pages)/uploaded-media/_components/MediaListField/MediaList.module.scss new file mode 100644 index 0000000..125a494 --- /dev/null +++ b/app/(pages)/uploaded-media/_components/MediaListField/MediaList.module.scss @@ -0,0 +1,96 @@ +@use 'media'; + +.container{ + display: flex; + flex-direction: column; + gap: var(--small-spacer); +} + +.card_container{ + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + padding: var(--spacer) var(--medium-spacer); + border-radius: var(--b-radius); + box-shadow: var(--b-shadow); + cursor: grab; +} + +.image_section_left { + display: flex; + flex-direction: row; + gap: var(--large-spacer); + align-items: center; + + .drag_icon{ + height: 1.5rem; + width: auto; + } + + .index { + font-size: 1.375rem; + font-weight: 300; + } + + .preview { + border-radius: var(--b-radius); + object-fit: cover; + object-position: center center; + height: 100%; + aspect-ratio: calc(3/2); + } + + .name_block { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 2px; + + .name{ + font-size: 1.25rem; + font-weight: 700; + } + + .upload_status { + color: var(--text-dark-gray); + font-family: var(--font-dm-sans); + font-size: 1rem; + font-weight: 700; + } + } +} + +.image_section_right { + display: flex; + flex-direction: row; + gap: var(--large-spacer); + align-items: center; + + + .replace{ + font-family: var(--font-dm-sans); + font-size: 1.375rem; + cursor: pointer; + font-weight: 500; + } + + .size { + font-family: var(--font-dm-sans); + font-size: 1.25rem; + } + + .delete { + height: 1.625rem; + width: auto; + cursor: pointer; + } +} + +.dragging { + opacity: 0.5; +} + +.dragover { + border: 2px dashed var(--text-dark); +} diff --git a/app/(pages)/uploaded-media/_components/MediaListField/MediaList.tsx b/app/(pages)/uploaded-media/_components/MediaListField/MediaList.tsx new file mode 100644 index 0000000..fc87390 --- /dev/null +++ b/app/(pages)/uploaded-media/_components/MediaListField/MediaList.tsx @@ -0,0 +1,139 @@ +'use client'; +import { useState, DragEvent } from 'react'; + +import useContentFormContext from '@hooks/useContentFormContext'; +import Image from 'next/image'; +import styles from './MediaList.module.scss'; +import dragIcon from '@public/content/form/drag-icon.png'; +import deleteIcon from '@public/content/form/delete.png'; +import MediaItem from '@typeDefs/media/MediaItem'; +import convertFileToMediaItem from '.app/(pages)/_utils/ConvertFileToMediaItem'; + +interface MediaListProps { + field_name: string; +} + +export default function MediaList({ field_name }: MediaListProps) { + const { data, updateField } = useContentFormContext(); + + const [draggedIndex, setDraggedIndex] = useState(-1); + const [newIndex, setNewIndex] = useState(-1); + + const formatFileSize = (size: number) => { + if (size === 0) return '0 Bytes'; + const units = ['Bytes', 'KB', 'MB', 'GB', 'TB']; + const unitIndex = Math.floor(Math.log(size) / Math.log(1024)); + const unitValue = Math.pow(1024, unitIndex); + const unitLabel = units[unitIndex]; + const formattedSize = (size / unitValue).toFixed(unitIndex === 0 ? 0 : 2); + return `${formattedSize} ${unitLabel}`; + }; + + const handleDelete = (index: number) => { + const updatedFiles = [...data[field_name]]; + updatedFiles.splice(index, 1); + updateField(field_name, updatedFiles); + }; + + const handleReplace = (index: number) => { + const input = document.createElement('input'); + input.type = 'file'; + input.addEventListener('change', (e) => { + const newFile = (e.target as HTMLInputElement).files?.[0]; + if (newFile) { + const updatedFiles = [...data[field_name]]; + const updatedFile = convertFileToMediaItem(newFile); + updatedFiles[index] = updatedFile; + updateField(field_name, updatedFiles); + } + }); + input.click(); + }; + + const handleDragStart = ( + e: DragEvent, + draggedIndex: number + ) => { + setDraggedIndex(draggedIndex); + }; + + const handleDragOver = (e: DragEvent, overIndex: number) => { + e.preventDefault(); + if (draggedIndex !== -1 && draggedIndex !== overIndex) { + setNewIndex(overIndex); + } + }; + + const handleDragLeave = () => { + setNewIndex(-1); + }; + + const handleDragEnd = () => { + if (draggedIndex !== -1 && newIndex !== -1) { + const updatedFiles = [...data[field_name]]; + const [draggedItem] = updatedFiles.splice(draggedIndex, 1); + updatedFiles.splice(newIndex, 0, draggedItem); + updateField(field_name, updatedFiles); + } + setDraggedIndex(-1); + setNewIndex(-1); + }; + + return ( +
+ {data[field_name].length === 0 ? ( +
No images/videos uploaded yet
+ ) : ( + data[field_name].map((file: MediaItem, index: number) => ( +
handleDragStart(e, index)} + onDragOver={(e) => handleDragOver(e, index)} + onDragEnd={handleDragEnd} + > +
+ draggable icon +

#{index + 1}

+ {file.name} +
+

{file.name}

+

+ {file.cloudinary_id ? 'Uploaded to cloud' : ' '} +

+
+
+
+

{formatFileSize(file.size)}

+
handleReplace(index)} + > + Replace Image +
+ delete icon handleDelete(index)} + /> +
+
+ )) + )} +
+ ); +} \ No newline at end of file diff --git a/app/(pages)/uploaded-media/_components/MediaListField/MediaListField.module.scss b/app/(pages)/uploaded-media/_components/MediaListField/MediaListField.module.scss new file mode 100644 index 0000000..691e9b4 --- /dev/null +++ b/app/(pages)/uploaded-media/_components/MediaListField/MediaListField.module.scss @@ -0,0 +1,5 @@ +.container { + display: flex; + flex-direction: column; + gap: var(--medium-spacer); +} diff --git a/app/(pages)/uploaded-media/_components/MediaListField/MediaListField.tsx b/app/(pages)/uploaded-media/_components/MediaListField/MediaListField.tsx new file mode 100644 index 0000000..b2d4937 --- /dev/null +++ b/app/(pages)/uploaded-media/_components/MediaListField/MediaListField.tsx @@ -0,0 +1,21 @@ +import styles from './MediaListField.module.scss'; + +import MediaList from './MediaList'; +import MediaSelector from '../MediaSelector/MediaSelector'; + +interface MediaItemFieldProps { + field_name: string; + initial_value?: string[]; +} + +export default function MediaListField({ + field_name, + initial_value: _, +}: MediaItemFieldProps) { + return ( +
+ + +
+ ); +} diff --git a/app/(pages)/_components/MediaSelector/MediaFromUpload.module.scss b/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.module.scss similarity index 100% rename from app/(pages)/_components/MediaSelector/MediaFromUpload.module.scss rename to app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.module.scss diff --git a/app/(pages)/_components/MediaSelector/MediaFromUpload.tsx b/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.tsx similarity index 100% rename from app/(pages)/_components/MediaSelector/MediaFromUpload.tsx rename to app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.tsx diff --git a/app/(pages)/_components/MediaSelector/MediaSelector.module.scss b/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.module.scss similarity index 100% rename from app/(pages)/_components/MediaSelector/MediaSelector.module.scss rename to app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.module.scss diff --git a/app/(pages)/_components/MediaSelector/MediaSelector.tsx b/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.tsx similarity index 96% rename from app/(pages)/_components/MediaSelector/MediaSelector.tsx rename to app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.tsx index 3640a90..ee8982b 100644 --- a/app/(pages)/_components/MediaSelector/MediaSelector.tsx +++ b/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.tsx @@ -1,6 +1,5 @@ 'use client'; import styles from './MediaSelector.module.scss'; -import MediaFromGallery from './MediaFromGallery'; import MediaFromUpload from './MediaFromUpload'; import useContentFormContext from '@hooks/useContentFormContext'; import convertFileToMediaItem from '../../_utils/convertFileToMediaItem'; diff --git a/app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss b/app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss similarity index 100% rename from app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss rename to app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss diff --git a/app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.tsx b/app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.tsx similarity index 77% rename from app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.tsx rename to app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.tsx index c385095..5d56e70 100644 --- a/app/(pages)/_components/UploadedMediaPopup/UploadedMediaPopup.tsx +++ b/app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.tsx @@ -5,10 +5,6 @@ import FilterContextProvider from '@app/(pages)/_contexts/FilterContext'; import MediaCard from '../MediaCard/MediaCard'; import useMedia from '@app/(pages)/_hooks/useMedia'; import MediaItem from '@app/_types/media/MediaItem'; -import ContentSection from '@components/ContentSection/ContentSection'; -import ContentFilters from '@components/ContentFilters/ContentFilters'; -import useContentFormContext from '@app/(pages)/_hooks/useContentFormContext'; -import useContentWindowContext from '@hooks/useContentWindowContext'; interface UploadedMediaPopupProps { fieldName: string; @@ -17,7 +13,6 @@ interface UploadedMediaPopupProps { export default function UploadedMediaPopup({ fieldName, }: UploadedMediaPopupProps) { - const { top, left, bottom, right } = useContentWindowContext(); const position = { top: `${top}px`, left: `${left}px`, @@ -27,7 +22,6 @@ export default function UploadedMediaPopup({ const { selectMode, toggleSelectMode, selectedIds } = useSelectContext(); const { loading, data: mediaData, error } = useMedia(); - const { updateField, data } = useContentFormContext(); if (loading) { return 'loading...'; @@ -57,9 +51,7 @@ export default function UploadedMediaPopup({

Uploaded Media

-
- {data_list}
diff --git a/app/(pages)/uploaded-media/page.module.scss b/app/(pages)/uploaded-media/page.module.scss new file mode 100644 index 0000000..eccea63 --- /dev/null +++ b/app/(pages)/uploaded-media/page.module.scss @@ -0,0 +1,8 @@ +@use 'media'; + +.container { + display: flex; + flex-direction: column; + margin: var(--medium-spacer) 0; + gap: var(--medium-spacer); +} diff --git a/app/(pages)/uploaded-media/page.tsx b/app/(pages)/uploaded-media/page.tsx new file mode 100644 index 0000000..1a5218a --- /dev/null +++ b/app/(pages)/uploaded-media/page.tsx @@ -0,0 +1,32 @@ +'use server'; +import styles from './page.module.scss'; + +import MediaCard from '@components/media/MediaCard/MediaCard'; +import MediaHeader from '@components/media/MediaHeader/MediaHeader'; +import ContentSection from '@components/media/ContentSection/ContentSection'; +import SelectContextProvider from '@contexts/SelectContext'; +import FilterContextProvider from '@contexts/FilterContext'; +import { findMediaItems } from '@datalib/media/findMediaItem'; +import MediaItem from '@typeDefs/media/MediaItem'; + +export default async function MediaPage() { + const res = JSON.parse(JSON.stringify(await findMediaItems())); + if (!res.ok) { + return 'Error fetching Media data'; + } + + const data_list = res.body.map((mediaItem: MediaItem) => { + return ; + }); + + return ( + + +
+ + {data_list} +
+
+
+ ); +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index c6c525a..d985a00 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,6 +24,7 @@ "@public/*": ["./public/*"], "@globals/*": ["./app/(pages)/_globals/*"], "@components/*": ["./app/(pages)/_components/*"], + "@components/media/*": ["./app/(pages)/uploaded-media/_components"], "@data/*": ["./app/(pages)/_data/*"], "@hooks/*": ["./app/(pages)/_hooks/*"], "@contexts/*": ["./app/(pages)/_contexts/*"], From c0be007953004379466839c825fdadf81caf5e27 Mon Sep 17 00:00:00 2001 From: hdjekso Date: Thu, 6 Mar 2025 21:05:05 -0800 Subject: [PATCH 5/8] fixed some errors --- .../MediaCard/MediaCard.module.scss | 96 ++++++------ .../_components/MediaCard/MediaCard.tsx | 2 +- .../MediaHeader/MediaHeader.module.scss | 118 +++++++-------- .../_components/MediaHeader/MediaHeader.tsx | 4 +- .../MediaItemField/MediaItemField.tsx | 2 +- .../MediaListField/MediaList.module.scss | 143 +++++++++--------- .../_components/MediaListField/MediaList.tsx | 2 +- .../MediaListField/MediaListField.module.scss | 6 +- .../MediaSelector/MediaFromUpload.module.scss | 18 +-- .../MediaSelector/MediaFromUpload.tsx | 7 +- .../MediaSelector/MediaSelector.module.scss | 44 +++--- .../MediaSelector/MediaSelector.tsx | 16 +- .../UploadedMediaPopup.module.scss | 97 ++++++------ .../UploadedMediaPopup/UploadedMediaPopup.tsx | 8 +- app/(pages)/uploaded-media/page.module.scss | 10 +- app/(pages)/uploaded-media/page.tsx | 2 +- tsconfig.json | 2 +- 17 files changed, 291 insertions(+), 286 deletions(-) diff --git a/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.module.scss b/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.module.scss index 805b681..7e33c37 100644 --- a/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.module.scss +++ b/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.module.scss @@ -1,67 +1,67 @@ .container { - display: flex; - flex-direction: column; - padding: var(--spacer); - gap: var(--small-spacer); - text-align: left; - border-radius: var(--c-radius); - box-shadow: var(--b-shadow); - background-color: var(--background-light); + display: flex; + flex-direction: column; + padding: var(--spacer); + gap: var(--small-spacer); + text-align: left; + border-radius: var(--c-radius); + box-shadow: var(--b-shadow); + background-color: var(--background-light); - min-width: 324px; - width: calc(calc(100% - 5 * var(--medium-spacer)) / 3); - max-width: 424px; - height: min-content; - cursor: pointer; + min-width: 324px; + width: calc(calc(100% - 5 * var(--medium-spacer)) / 3); + max-width: 424px; + height: min-content; + cursor: pointer; } .top_row { - display: flex; - flex-direction: row; - align-items: center; - gap: var(--small-spacer); + display: flex; + flex-direction: row; + align-items: center; + gap: var(--small-spacer); - h2 { - font-size: 1.5rem; - font-weight: 400; - overflow: hidden; - text-overflow: ellipsis; - text-wrap: nowrap; - } + h2 { + font-size: 1.5rem; + font-weight: 400; + overflow: hidden; + text-overflow: ellipsis; + text-wrap: nowrap; + } - .checkbox_container { - height: 1.5rem; - aspect-ratio: 1; - border-radius: 4px; - border: solid 1px black; - overflow: hidden; - flex-shrink: 0; + .checkbox_container { + height: 1.5rem; + aspect-ratio: 1; + border-radius: 4px; + border: solid 1px black; + overflow: hidden; + flex-shrink: 0; - .checkbox_internals { - position: relative; - background-color: var(--primary); - display: flex; - height: 100%; - width: 100%; - } + .checkbox_internals { + position: relative; + background-color: var(--primary); + display: flex; + height: 100%; + width: 100%; } + } } .last_edited { - font-size: 0.875rem; - color: var(--text-dark-gray); + font-size: 0.875rem; + color: var(--text-dark-gray); } .kebab_button { - .kebab { - font-size: 1.5rem; - } + .kebab { + font-size: 1.5rem; + } } .media_container { - width: 100%; - aspect-ratio: 1.52; - position: relative; - overflow: hidden; - border-radius: var(--b-radius); + width: 100%; + aspect-ratio: 1.52; + position: relative; + overflow: hidden; + border-radius: var(--b-radius); } diff --git a/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.tsx b/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.tsx index 7ad54be..0573da2 100644 --- a/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.tsx +++ b/app/(pages)/uploaded-media/_components/MediaCard/MediaCard.tsx @@ -47,4 +47,4 @@ export default function MediaCard({ mediaItem }: Props) {
{preview}
); -} \ No newline at end of file +} diff --git a/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.module.scss b/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.module.scss index 7abc3e5..41b6060 100644 --- a/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.module.scss +++ b/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.module.scss @@ -1,78 +1,78 @@ .container { - display: flex; - flex-direction: column; - gap: var(--spacer); - padding: 0 var(--medium-spacer); + display: flex; + flex-direction: column; + gap: var(--spacer); + padding: 0 var(--medium-spacer); - >div { - display: flex; - flex-direction: row; - } + > div { + display: flex; + flex-direction: row; + } } .top_row { - justify-content: space-between; - align-items: center; - >h1 { - font-size: 3rem; - font-weight: 700; - } + justify-content: space-between; + align-items: center; + > h1 { + font-size: 3rem; + font-weight: 700; + } - .top_right { - display: flex; - flex-direction: row; - gap: var(--small-spacer); - } -} - -.bot_row { + .top_right { display: flex; flex-direction: row; gap: var(--small-spacer); + } +} + +.bot_row { + display: flex; + flex-direction: row; + gap: var(--small-spacer); } .select_button_container { - display: flex; - flex-direction: row; - gap: var(--spacer); - align-items: center; - padding: var(--small-spacer) var(--spacer); - background-color: var(--background-light); - border-radius: var(--b-radius); - box-shadow: var(-b-shadow); + display: flex; + flex-direction: row; + gap: var(--spacer); + align-items: center; + padding: var(--small-spacer) var(--spacer); + background-color: var(--background-light); + border-radius: var(--b-radius); + box-shadow: var(-b-shadow); - .select_button_icon { - height: 24px; - aspect-ratio: 1; - border-radius: 4px; - border: solid 1px black; - } + .select_button_icon { + height: 24px; + aspect-ratio: 1; + border-radius: 4px; + border: solid 1px black; + } - >p { - color: var(--primary); - font-size: 1.375rem; - font-weight: 500; - } + > p { + color: var(--primary); + font-size: 1.375rem; + font-weight: 500; + } } .trash_button_container { - padding: var(--small-spacer) var(--spacer); - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - gap: var(--tiny-spacer); - background-color: var(--red); - border-radius: var(--b-radius); + padding: var(--small-spacer) var(--spacer); + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: var(--tiny-spacer); + background-color: var(--red); + border-radius: var(--b-radius); - > h4 { - font-size: 1.375rem; - font-weight: 500; - color: var(--text-light); - } + > h4 { + font-size: 1.375rem; + font-weight: 500; + color: var(--text-light); + } - .trash_button_trash_icon { - height: 100%; - width: auto; - } -} \ No newline at end of file + .trash_button_trash_icon { + height: 100%; + width: auto; + } +} diff --git a/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.tsx b/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.tsx index 835a717..472d4e3 100644 --- a/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.tsx +++ b/app/(pages)/uploaded-media/_components/MediaHeader/MediaHeader.tsx @@ -1,10 +1,10 @@ 'use client'; import useSelectContext from '@hooks/useSelectContext'; -import Image from 'next/image'; +//import Image from "next/image"; //import { DeleteMediaItem } from '@actions/media/deleteMediaItem'; import styles from './MediaHeader.module.scss'; -import trash from '@public/content/[content_type]/trash.svg'; +//import trash from "@public/content/[content_type]/trash.svg"; export default function MediaHeader() { const { selectMode, toggleSelectMode, selectedIds } = useSelectContext(); diff --git a/app/(pages)/uploaded-media/_components/MediaItemField/MediaItemField.tsx b/app/(pages)/uploaded-media/_components/MediaItemField/MediaItemField.tsx index 0362f23..6e82151 100644 --- a/app/(pages)/uploaded-media/_components/MediaItemField/MediaItemField.tsx +++ b/app/(pages)/uploaded-media/_components/MediaItemField/MediaItemField.tsx @@ -10,4 +10,4 @@ export default function MediaItemField({ initial_value: __, }: MediaItemFieldProps) { return
MediaItemField
; -} \ No newline at end of file +} diff --git a/app/(pages)/uploaded-media/_components/MediaListField/MediaList.module.scss b/app/(pages)/uploaded-media/_components/MediaListField/MediaList.module.scss index 125a494..1221145 100644 --- a/app/(pages)/uploaded-media/_components/MediaListField/MediaList.module.scss +++ b/app/(pages)/uploaded-media/_components/MediaListField/MediaList.module.scss @@ -1,96 +1,95 @@ -@use 'media'; +@use "media"; -.container{ - display: flex; - flex-direction: column; - gap: var(--small-spacer); +.container { + display: flex; + flex-direction: column; + gap: var(--small-spacer); } -.card_container{ - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - padding: var(--spacer) var(--medium-spacer); - border-radius: var(--b-radius); - box-shadow: var(--b-shadow); - cursor: grab; +.card_container { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + padding: var(--spacer) var(--medium-spacer); + border-radius: var(--b-radius); + box-shadow: var(--b-shadow); + cursor: grab; } .image_section_left { - display: flex; - flex-direction: row; - gap: var(--large-spacer); - align-items: center; + display: flex; + flex-direction: row; + gap: var(--large-spacer); + align-items: center; - .drag_icon{ - height: 1.5rem; - width: auto; - } + .drag_icon { + height: 1.5rem; + width: auto; + } - .index { - font-size: 1.375rem; - font-weight: 300; - } + .index { + font-size: 1.375rem; + font-weight: 300; + } + + .preview { + border-radius: var(--b-radius); + object-fit: cover; + object-position: center center; + height: 100%; + aspect-ratio: calc(3 / 2); + } - .preview { - border-radius: var(--b-radius); - object-fit: cover; - object-position: center center; - height: 100%; - aspect-ratio: calc(3/2); + .name_block { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 2px; + + .name { + font-size: 1.25rem; + font-weight: 700; } - .name_block { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 2px; - - .name{ - font-size: 1.25rem; - font-weight: 700; - } - - .upload_status { - color: var(--text-dark-gray); - font-family: var(--font-dm-sans); - font-size: 1rem; - font-weight: 700; - } + .upload_status { + color: var(--text-dark-gray); + font-family: var(--font-dm-sans); + font-size: 1rem; + font-weight: 700; } + } } .image_section_right { - display: flex; - flex-direction: row; - gap: var(--large-spacer); - align-items: center; + display: flex; + flex-direction: row; + gap: var(--large-spacer); + align-items: center; + .replace { + font-family: var(--font-dm-sans); + font-size: 1.375rem; + cursor: pointer; + font-weight: 500; + } - .replace{ - font-family: var(--font-dm-sans); - font-size: 1.375rem; - cursor: pointer; - font-weight: 500; - } + .size { + font-family: var(--font-dm-sans); + font-size: 1.25rem; + } - .size { - font-family: var(--font-dm-sans); - font-size: 1.25rem; - } - - .delete { - height: 1.625rem; - width: auto; - cursor: pointer; - } + .delete { + height: 1.625rem; + width: auto; + cursor: pointer; + } } .dragging { - opacity: 0.5; + opacity: 0.5; } - + .dragover { - border: 2px dashed var(--text-dark); + border: 2px dashed var(--text-dark); } diff --git a/app/(pages)/uploaded-media/_components/MediaListField/MediaList.tsx b/app/(pages)/uploaded-media/_components/MediaListField/MediaList.tsx index fc87390..abc6a54 100644 --- a/app/(pages)/uploaded-media/_components/MediaListField/MediaList.tsx +++ b/app/(pages)/uploaded-media/_components/MediaListField/MediaList.tsx @@ -136,4 +136,4 @@ export default function MediaList({ field_name }: MediaListProps) { )} ); -} \ No newline at end of file +} diff --git a/app/(pages)/uploaded-media/_components/MediaListField/MediaListField.module.scss b/app/(pages)/uploaded-media/_components/MediaListField/MediaListField.module.scss index 691e9b4..705750b 100644 --- a/app/(pages)/uploaded-media/_components/MediaListField/MediaListField.module.scss +++ b/app/(pages)/uploaded-media/_components/MediaListField/MediaListField.module.scss @@ -1,5 +1,5 @@ .container { - display: flex; - flex-direction: column; - gap: var(--medium-spacer); + display: flex; + flex-direction: column; + gap: var(--medium-spacer); } diff --git a/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.module.scss b/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.module.scss index e410ceb..3401efc 100644 --- a/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.module.scss +++ b/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.module.scss @@ -1,11 +1,11 @@ .container { - border: 1px dashed var(--text-dark); - border-radius: var(--b-radius); - padding: var(--large-spacer) var(--medium-spacer); - text-align: center; - cursor: pointer; + border: 1px dashed var(--text-dark); + border-radius: var(--b-radius); + padding: var(--large-spacer) var(--medium-spacer); + text-align: center; + cursor: pointer; - >input { - display: none; - } -} \ No newline at end of file + > input { + display: none; + } +} diff --git a/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.tsx b/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.tsx index c08005b..5a948cf 100644 --- a/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.tsx +++ b/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.tsx @@ -33,22 +33,21 @@ export default function MediaFromUpload({ onInput }: MediaFromUploadProps) { //new function const processFiles = async (files: FileList) => { const uploadedMediaItems = []; - + for (const file of Array.from(files)) { const mediaItem = { type: file.type.startsWith('video') ? 'video' : 'image', src: URL.createObjectURL(file), // Temporary preview URL }; - + const response = await uploadMediaItem(mediaItem); //call backend function if (response.ok) { uploadedMediaItems.push(response.body); } } - + onInput(uploadedMediaItems); // Calls the function with new media items }; - const handleDragOver = (e: DragEvent) => { e.preventDefault(); diff --git a/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.module.scss b/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.module.scss index 050358b..6ec2144 100644 --- a/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.module.scss +++ b/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.module.scss @@ -1,29 +1,29 @@ -@use 'media'; +@use "media"; .container { - display: grid; - grid-template-columns: 1fr auto 1fr; - gap: var(--small-spacer); - h4 { - font-weight: 400; - } + display: grid; + grid-template-columns: 1fr auto 1fr; + gap: var(--small-spacer); + h4 { + font-weight: 400; + } } -.or_container{ - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - gap: var(--tiny-spacer); - @include media.tablet { - flex-direction: row; - } +.or_container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: var(--tiny-spacer); + @include media.tablet { + flex-direction: row; + } } .line { - border-left: 1px solid var(--text-dark); - height: 25px; - @include media.tablet { - display: none; - } -} \ No newline at end of file + border-left: 1px solid var(--text-dark); + height: 25px; + @include media.tablet { + display: none; + } +} diff --git a/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.tsx b/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.tsx index ee8982b..34f9a55 100644 --- a/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.tsx +++ b/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.tsx @@ -2,8 +2,8 @@ import styles from './MediaSelector.module.scss'; import MediaFromUpload from './MediaFromUpload'; import useContentFormContext from '@hooks/useContentFormContext'; -import convertFileToMediaItem from '../../_utils/convertFileToMediaItem'; -import SelectContextProvider from '@app/(pages)/_contexts/SelectContext'; +//import convertFileToMediaItem from "../../_utils/convertFileToMediaItem"; +//import SelectContextProvider from "@app/(pages)/_contexts/SelectContext"; interface MediaSelectorProps { field_name: string; @@ -19,12 +19,18 @@ export default function MediaSelector({ field_name }: MediaSelectorProps) { ]; updateField(field_name, updatedFieldValue); };*/ - const onInput = (uploadedMediaItems: any[]) => { //files are already processed, not in raw format + const onInput = (uploadedMediaItems: any[]) => { + //files are already processed, not in raw format const updatedFieldValue = [...data[field_name], ...uploadedMediaItems]; updateField(field_name, updatedFieldValue); }; return ( +
+ +
+ ); + /*return (
@@ -36,5 +42,5 @@ export default function MediaSelector({ field_name }: MediaSelectorProps) {
- ); -} \ No newline at end of file + );*/ +} diff --git a/app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss b/app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss index 377c5c8..4ceb5a7 100644 --- a/app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss +++ b/app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.module.scss @@ -1,64 +1,65 @@ .container { - position: fixed; - display: flex; - flex-direction: column; - display: none; - background-color: var(--background-primary); - overflow-y: scroll; - padding-bottom: var(--enormous-spacer); + position: fixed; + display: flex; + flex-direction: column; + display: none; + background-color: var(--background-primary); + overflow-y: scroll; + padding-bottom: var(--enormous-spacer); - &.visible { - display: flex; - } + &.visible { + display: flex; + } } .header { - display: flex; - flex-direction: column; - padding: 0 var(--medium-spacer); - gap: var(--spacer); + display: flex; + flex-direction: column; + padding: 0 var(--medium-spacer); + gap: var(--spacer); - .title { - font-size: 3rem; - font-weight: 700; - } + .title { + font-size: 3rem; + font-weight: 700; + } } .data_container { - display: flex; - flex-direction: column; - margin: var(--medium-spacer) 0; - gap: var(--medium-spacer); + display: flex; + flex-direction: column; + margin: var(--medium-spacer) 0; + gap: var(--medium-spacer); } .button_container { + display: flex; + flex-direction: row; + gap: var(--spacer); + justify-content: center; + margin-top: var(--medium-spacer); + + .attach, + .exit_button { + border-radius: 8px; + box-shadow: 0px 4px 35px 0px rgba(60, 37, 126, 0.4); display: flex; - flex-direction: row; - gap: var(--spacer); + padding: 20px 36px; justify-content: center; - margin-top: var(--medium-spacer); - - .attach, .exit_button { - border-radius: 8px; - box-shadow: 0px 4px 35px 0px rgba(60, 37, 126, 0.40); - display: flex; - padding: 20px 36px; - justify-content: center; - align-items: center; - color: #FFF; - font-family: var(--font-dm-sans); - font-size: 1.5rem; - font-weight: 500; - color: var(--text-light); - } + align-items: center; + color: #fff; + font-family: var(--font-dm-sans); + font-size: 1.5rem; + font-weight: 500; + color: var(--text-light); + } - .attach { - background: var(--primary); - width: 480px; - } + .attach { + background: var(--primary); + width: 480px; + } - .exit_button { - background: var(--red); - padding: 20px 58px; - } -} \ No newline at end of file + .exit_button { + background: var(--red); + padding: 20px 58px; + } +} diff --git a/app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.tsx b/app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.tsx index 5d56e70..5388c4a 100644 --- a/app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.tsx +++ b/app/(pages)/uploaded-media/_components/UploadedMediaPopup/UploadedMediaPopup.tsx @@ -2,9 +2,9 @@ import styles from './UploadedMediaPopup.module.scss'; import useSelectContext from '@app/(pages)/_hooks/useSelectContext'; import FilterContextProvider from '@app/(pages)/_contexts/FilterContext'; -import MediaCard from '../MediaCard/MediaCard'; +//import MediaCard from '../MediaCard/MediaCard'; import useMedia from '@app/(pages)/_hooks/useMedia'; -import MediaItem from '@app/_types/media/MediaItem'; +//import MediaItem from '@app/_types/media/MediaItem'; interface UploadedMediaPopupProps { fieldName: string; @@ -31,9 +31,9 @@ export default function UploadedMediaPopup({ return error; } - const data_list = mediaData.map((mediaItem: MediaItem) => { + /*const data_list = mediaData.map((mediaItem: MediaItem) => { return ; - }); + });*/ const attachMedia = () => { const selectedMedia = Object.values(selectedIds).filter(Boolean); diff --git a/app/(pages)/uploaded-media/page.module.scss b/app/(pages)/uploaded-media/page.module.scss index eccea63..b120c1d 100644 --- a/app/(pages)/uploaded-media/page.module.scss +++ b/app/(pages)/uploaded-media/page.module.scss @@ -1,8 +1,8 @@ -@use 'media'; +@use "media"; .container { - display: flex; - flex-direction: column; - margin: var(--medium-spacer) 0; - gap: var(--medium-spacer); + display: flex; + flex-direction: column; + margin: var(--medium-spacer) 0; + gap: var(--medium-spacer); } diff --git a/app/(pages)/uploaded-media/page.tsx b/app/(pages)/uploaded-media/page.tsx index 1a5218a..3009434 100644 --- a/app/(pages)/uploaded-media/page.tsx +++ b/app/(pages)/uploaded-media/page.tsx @@ -29,4 +29,4 @@ export default async function MediaPage() { ); -} \ No newline at end of file +} diff --git a/tsconfig.json b/tsconfig.json index d985a00..3a365c4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,7 +28,7 @@ "@data/*": ["./app/(pages)/_data/*"], "@hooks/*": ["./app/(pages)/_hooks/*"], "@contexts/*": ["./app/(pages)/_contexts/*"], - "@utils/*": ["./app/(api)/_utils/*"], + "@utils/*": ["./app/(pages)/_utils/*"], "@pageUtils/*": ["./app/(pages)/_utils/*"], "@actions/*": ["./app/(api)/_actions/*"], "@graphql/*": ["./app/(pages)/_graphql/*"], From 016164cd248f6eaa1b5545c56be438cc2f554e7b Mon Sep 17 00:00:00 2001 From: palina0k Date: Mon, 10 Mar 2025 10:42:37 -0700 Subject: [PATCH 6/8] very minor changes - possible reason for errors at the moment: no media folder under (api)/_typedefs and (api)/_datalib with the appropriate mediaItem and findMediaItem that are called in (pages)/uploaded-media/page.tsx --- app/(pages)/uploaded-media/page.tsx | 10 +++++----- tsconfig.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/(pages)/uploaded-media/page.tsx b/app/(pages)/uploaded-media/page.tsx index 3009434..1b089d1 100644 --- a/app/(pages)/uploaded-media/page.tsx +++ b/app/(pages)/uploaded-media/page.tsx @@ -1,13 +1,13 @@ 'use server'; import styles from './page.module.scss'; -import MediaCard from '@components/media/MediaCard/MediaCard'; -import MediaHeader from '@components/media/MediaHeader/MediaHeader'; -import ContentSection from '@components/media/ContentSection/ContentSection'; +import MediaCard from '@componentsmedia/MediaCard/MediaCard'; +import MediaHeader from '@componentsmedia/MediaHeader/MediaHeader'; +import ContentSection from '@componentsmedia/ContentSection/ContentSection'; import SelectContextProvider from '@contexts/SelectContext'; import FilterContextProvider from '@contexts/FilterContext'; -import { findMediaItems } from '@datalib/media/findMediaItem'; -import MediaItem from '@typeDefs/media/MediaItem'; +import { findMediaItems } from '@datalib/media/findMediaItem'; //no media folder under ./app/(api)/_datalib and no findMediaItem function yet +import MediaItem from '@typeDefs/media/MediaItem'; //no media folder under ./app/(api)/_types and no typeDef for Media Item yet export default async function MediaPage() { const res = JSON.parse(JSON.stringify(await findMediaItems())); diff --git a/tsconfig.json b/tsconfig.json index 3a365c4..c594bc2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,7 +24,7 @@ "@public/*": ["./public/*"], "@globals/*": ["./app/(pages)/_globals/*"], "@components/*": ["./app/(pages)/_components/*"], - "@components/media/*": ["./app/(pages)/uploaded-media/_components"], + "@componentsmedia/*": ["./app/(pages)/uploaded-media/_components"], "@data/*": ["./app/(pages)/_data/*"], "@hooks/*": ["./app/(pages)/_hooks/*"], "@contexts/*": ["./app/(pages)/_contexts/*"], From 798473c7b121a9f8849f81298f6ff0562d1b7c84 Mon Sep 17 00:00:00 2001 From: hdjekso Date: Mon, 24 Mar 2025 23:05:44 -0700 Subject: [PATCH 7/8] removed ny[] usage and added findMediaItem.ts, _datalib/findMediaItem.ts needs fixing --- app/(api)/_actions/media/findMediaItem.ts | 11 +++++ app/(api)/_datalib/media/findMediaItem.ts | 42 +++++++++++++++++++ app/(pages)/_hooks/useMedia.ts | 2 +- .../MediaSelector/MediaFromUpload.tsx | 5 +-- .../MediaSelector/MediaSelector.tsx | 9 +--- tsconfig.json | 1 + 6 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 app/(api)/_actions/media/findMediaItem.ts create mode 100644 app/(api)/_datalib/media/findMediaItem.ts diff --git a/app/(api)/_actions/media/findMediaItem.ts b/app/(api)/_actions/media/findMediaItem.ts new file mode 100644 index 0000000..7b528e1 --- /dev/null +++ b/app/(api)/_actions/media/findMediaItem.ts @@ -0,0 +1,11 @@ +'use server'; + +import { findMediaItem, findMediaItems } from '@datalib/media/findMediaItem'; + +export async function FindMediaItem(id: string) { + return findMediaItem(id); +} + +export async function FindMediaItems(query: object = {}) { + return findMediaItems(query); +} \ No newline at end of file diff --git a/app/(api)/_datalib/media/findMediaItem.ts b/app/(api)/_datalib/media/findMediaItem.ts new file mode 100644 index 0000000..8767459 --- /dev/null +++ b/app/(api)/_datalib/media/findMediaItem.ts @@ -0,0 +1,42 @@ +import { ObjectId } from 'mongodb'; +import { getDatabase } from '@utils/mongodb/mongoClient.mjs'; +import { HttpError, NotFoundError } from '@utils/response/Errors'; + +export async function findMediaItem(id: string) { + try { + const db = await getDatabase(); + const objectId = ObjectId.createFromHexString(id); + + const mediaItem = await db.collection('media').findOne({ + _id: objectId, + }); + + if (!mediaItem) { + throw new NotFoundError(`Media item with id: ${id} not found.`); + } + + return { ok: true, body: mediaItem, error: null }; + } catch (error) { + const e = error as HttpError; + return { + ok: false, + body: null, + error: e.message || 'Internal Server Error', + }; + } +} + +export async function findMediaItems(query: object = {}) { + try { + const db = await getDatabase(); + const mediaItems = await db.collection('media').find(query).toArray(); + return { ok: true, body: mediaItems, error: null }; + } catch (error) { + const e = error as HttpError; + return { + ok: false, + body: null, + error: e.message || 'Internal Server Error', + }; + } +} \ No newline at end of file diff --git a/app/(pages)/_hooks/useMedia.ts b/app/(pages)/_hooks/useMedia.ts index 1e903da..36ccacc 100644 --- a/app/(pages)/_hooks/useMedia.ts +++ b/app/(pages)/_hooks/useMedia.ts @@ -1,4 +1,4 @@ -import MediaItem from '@app/_types/media/MediaItem'; +import MediaItem from '../_types/media/MediaItem'; import { useState, useEffect } from 'react'; import { FindMediaItems } from '@app/(api)/_actions/media/findMediaItem'; diff --git a/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.tsx b/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.tsx index 5a948cf..2a70edf 100644 --- a/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.tsx +++ b/app/(pages)/uploaded-media/_components/MediaSelector/MediaFromUpload.tsx @@ -4,11 +4,10 @@ import Image from 'next/image'; import styles from './MediaFromUpload.module.scss'; import uploadIcon from '@public/content/form/upload.png'; -import uploadMediaItem from '@utils/uploadMediaItem'; +import uploadMediaItem from '@utils/uploadMediaItem'; //backend function from vinay/ kiran interface MediaFromUploadProps { - //onInput: (files: FileList) => void; - onInput: (mediaItems: any[]) => void; + onInput: (files: FileList) => void; } export default function MediaFromUpload({ onInput }: MediaFromUploadProps) { diff --git a/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.tsx b/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.tsx index 34f9a55..b432a72 100644 --- a/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.tsx +++ b/app/(pages)/uploaded-media/_components/MediaSelector/MediaSelector.tsx @@ -2,7 +2,7 @@ import styles from './MediaSelector.module.scss'; import MediaFromUpload from './MediaFromUpload'; import useContentFormContext from '@hooks/useContentFormContext'; -//import convertFileToMediaItem from "../../_utils/convertFileToMediaItem"; +import convertFileToMediaItem from '@utils/convertFileToMediaItem'; //import SelectContextProvider from "@app/(pages)/_contexts/SelectContext"; interface MediaSelectorProps { @@ -12,17 +12,12 @@ interface MediaSelectorProps { export default function MediaSelector({ field_name }: MediaSelectorProps) { const { data, updateField } = useContentFormContext(); - /*const onInput = (files: FileList) => { + const onInput = (files: FileList) => { const updatedFieldValue = [ ...data[field_name], ...Array.from(files).map(convertFileToMediaItem), ]; updateField(field_name, updatedFieldValue); - };*/ - const onInput = (uploadedMediaItems: any[]) => { - //files are already processed, not in raw format - const updatedFieldValue = [...data[field_name], ...uploadedMediaItems]; - updateField(field_name, updatedFieldValue); }; return ( diff --git a/tsconfig.json b/tsconfig.json index c594bc2..10e9d79 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,6 +27,7 @@ "@componentsmedia/*": ["./app/(pages)/uploaded-media/_components"], "@data/*": ["./app/(pages)/_data/*"], "@hooks/*": ["./app/(pages)/_hooks/*"], + "@types/*": ["./app/(pages)/_types/*"], "@contexts/*": ["./app/(pages)/_contexts/*"], "@utils/*": ["./app/(pages)/_utils/*"], "@pageUtils/*": ["./app/(pages)/_utils/*"], From 87359f241a7be82d392b265b7aac90700ff6b62a Mon Sep 17 00:00:00 2001 From: hdjekso Date: Mon, 24 Mar 2025 23:07:14 -0700 Subject: [PATCH 8/8] modified MediaItem import path in page.tsx --- app/(pages)/uploaded-media/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/(pages)/uploaded-media/page.tsx b/app/(pages)/uploaded-media/page.tsx index 1b089d1..12e1c2b 100644 --- a/app/(pages)/uploaded-media/page.tsx +++ b/app/(pages)/uploaded-media/page.tsx @@ -7,7 +7,7 @@ import ContentSection from '@componentsmedia/ContentSection/ContentSection'; import SelectContextProvider from '@contexts/SelectContext'; import FilterContextProvider from '@contexts/FilterContext'; import { findMediaItems } from '@datalib/media/findMediaItem'; //no media folder under ./app/(api)/_datalib and no findMediaItem function yet -import MediaItem from '@typeDefs/media/MediaItem'; //no media folder under ./app/(api)/_types and no typeDef for Media Item yet +import MediaItem from '@app/(pages)/_types/media/MediaItem'; export default async function MediaPage() { const res = JSON.parse(JSON.stringify(await findMediaItems()));