first commit

This commit is contained in:
2025-03-25 11:47:41 +05:30
commit 61b3c4ee2c
211 changed files with 36430 additions and 0 deletions

View File

@@ -0,0 +1,128 @@
import React, { useState } from "react";
import RenderOverlay from "./Overlay";
import { ArrowIcon, CloseIcon } from "../icons/ExportCommonIcons";
import { AccessOption, User } from "../../types/users";
import RegularDropDown from "../ui/inputs/RegularDropDown";
import { access } from "fs";
import MultiEmailInvite from "../ui/inputs/MultiEmailInvite";
interface UserListTemplateProps {
user: User;
}
const UserListTemplate: React.FC<UserListTemplateProps> = ({ user }) => {
const [accessSelection, setAccessSelection] = useState<string>(user.access);
function accessUpdate({ option }: AccessOption) {
setAccessSelection(option);
}
return (
<div className="user-list-container">
<div className="user-details">
<div className="profile-image">
{user.profileImage ? (
<img
src={user.profileImage || "https://via.placeholder.com/150"}
alt={`${user.name}'s profile`}
/>
) : (
<div
className="no-profile-container"
style={{ background: user.color }}
>
{user.name[0]}
</div>
)}
</div>
<div className="user-name">{user.name}</div>
</div>
<div className="user-access">
<RegularDropDown
header={accessSelection}
options={["Admin", "User", "Viewer"]}
onSelect={(option) => accessUpdate({ option })}
search={false}
/>
{/* <ArrowIcon /> */}
</div>
</div>
);
};
const CollaborationPopup: React.FC = () => {
const users = [
{
name: "Alice Johnson",
email: "alice.johnson@example.com",
profileImage: "",
color: "#FF6600",
access: "Admin",
},
{
name: "Bob Smith",
email: "bob.smith@example.com",
profileImage: "",
color: "#488EF6",
access: "Viewer",
},
{
name: "Charlie Brown",
email: "charlie.brown@example.com",
profileImage: "",
color: "#48AC2A",
access: "Viewer",
},
{
name: "Diana Prince",
email: "diana.prince@example.com",
profileImage: "",
color: "#D44242",
access: "Viewer",
},
];
return (
<RenderOverlay>
<div className="collaboration-popup-wrapper">
<div className="collaboration-popup-container">
<div className="header">
<div className="content">Share this file</div>
<div className="content">
<div className="copy-link-button">copy link</div>
<div className="close-button">
<CloseIcon />
</div>
</div>
</div>
<div className="invite-input-container">
<MultiEmailInvite />
</div>
<div className="split"></div>
<div className="access-and-user-control-container">
<div className="user-header">Who has access</div>
<div className="general-access-container">
<div className="team-container">
<div className="project-name">Untitled</div>
<div className="number-of-peoples-have-access">
{users.length} persons
</div>
</div>
</div>
<div className="users-list-container">
<div className="you-container">
<div className="your-name">User 1</div>
<div className="indicater">you</div>
</div>
{users.map((user, index) => (
<UserListTemplate key={index} user={user} />
))}
</div>
</div>
</div>
</div>
</RenderOverlay>
);
};
export default CollaborationPopup;

View File

@@ -0,0 +1,39 @@
import React from "react";
import RenderOverlay from "./Overlay";
import { LogoIconLarge } from "../icons/Logo";
interface LoadingPageProps {
progress: number; // Expect progress as a percentage (0-100)
}
const LoadingPage: React.FC<LoadingPageProps> = ({ progress }) => {
// Ensure progress stays within 0-100 range
const validatedProgress = Math.min(100, Math.max(0, progress));
return (
<RenderOverlay>
<div className="loading-wrapper">
<div className="loading-container">
<div className="project-name">Untitled</div>
<div className="loading-hero-container">
<div className="logo">
<LogoIconLarge />
</div>
<div className="content">Entering A New World of Dwinzo</div>
</div>
<div className="progress-container">
<div className="progress-value">{validatedProgress}%</div>
<div className="progress-indicator-container">
<div
className="progress-bar"
style={{ width: `${validatedProgress}%` }} // Dynamic width
></div>
</div>
</div>
</div>
</div>
</RenderOverlay>
);
};
export default LoadingPage;

View File

@@ -0,0 +1,21 @@
import { ReactNode } from "react";
import ReactDOM from "react-dom";
// Define the props interface for the component, which requires `children` as a ReactNode type
interface PortalProps {
children: ReactNode;
}
// The `RenderOverlay` component allows rendering of its children into a specific DOM node (`root-over`) outside of the regular React component tree
const RenderOverlay = ({ children }: PortalProps) => {
// Retrieve the DOM element with the id `root-over` which serves as the mounting point for the overlay content.
const rootOver = document.getElementById("root-over");
// If the `rootOver` element exists in the DOM, use `ReactDOM.createPortal` to render the `children` inside this element
// `ReactDOM.createPortal` allows rendering outside of the usual React component tree, useful for overlays, modals, and tooltips
// If `rootOver` is null (i.e., does not exist), return null, rendering nothing
return rootOver ? ReactDOM.createPortal(children, rootOver) : null;
};
// Export the `RenderOverlay` component as the default export for use in other parts of the application
export default RenderOverlay;

View File

@@ -0,0 +1,74 @@
import React, { createContext, useContext, useState, ReactNode } from "react";
type Toast = {
id: string;
message: string;
type: "success" | "error" | "info" | "warning";
position?: ToastPosition; // Optional position for each toast
};
type ToastPosition =
| "top-left"
| "top-center"
| "top-right"
| "bottom-left"
| "bottom-center"
| "bottom-right";
type ToastContextType = {
addToast: (
message: string,
type: Toast["type"],
position?: ToastPosition
) => void;
removeToast: (id: string) => void;
};
const ToastContext = createContext<ToastContextType | undefined>(undefined);
const ToastProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const [toasts, setToasts] = useState<Toast[]>([]);
const addToast = (
message: string,
type: Toast["type"],
position: ToastPosition = "bottom-center" // Default position
) => {
const id = Math.random().toString(36).substr(2, 9); // Generate a unique ID
setToasts((prev) => [...prev, { id, message, type, position }]);
// Auto-remove toast after 3 seconds
setTimeout(() => removeToast(id), 3000);
};
const removeToast = (id: string) => {
setToasts((prev) => prev.filter((toast) => toast.id !== id));
};
return (
<ToastContext.Provider value={{ addToast, removeToast }}>
{children}
<div className={`toast-container ${"bottom-center"}`}>
{toasts.map((toast) => (
<div
key={toast.id}
className={`toast ${toast.type}`}
onClick={() => removeToast(toast.id)} // Allow manual dismissal
>
{toast.message}
</div>
))}
</div>
</ToastContext.Provider>
);
};
export const useToast = (): ToastContextType => {
const context = useContext(ToastContext);
if (!context) {
throw new Error("useToast must be used within a ToastProvider");
}
return context;
};
export default ToastProvider;