This commit is contained in:
Anton Tranelis 2024-10-08 08:32:10 +02:00
commit f23ea88e31
12 changed files with 419 additions and 36 deletions

View File

@ -0,0 +1,29 @@
import { useNavigate } from "react-router-dom"
import { useAuth } from "../../../Auth";
export const GratitudeControl = () => {
const navigate = useNavigate();
const {isAuthenticated} = useAuth();
if(isAuthenticated) return (
<div className="tw-card tw-bg-base-100 tw-shadow-xl tw-mt-2 tw-w-fit">
{
<div className="tw-card-body hover:tw-bg-slate-300 tw-card tw-p-2 tw-h-10 tw-w-10 tw-transition-all tw-duration-300 hover:tw-cursor-pointer" onClick={() => {
navigate("/select-user")
}}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" />
</svg>
</div>
}
</div>
)
else return (<></>);
}

View File

@ -9,9 +9,8 @@ import AddButton from "./Subcomponents/AddButton";
import { useEffect, useState } from "react";
import { ItemFormPopupProps } from "./Subcomponents/ItemFormPopup";
import { SearchControl } from "./Subcomponents/Controls/SearchControl";
// import { QuestControl } from "./Subcomponents/Controls/QuestControl";
import { Control } from "./Subcomponents/Controls/Control";
import { Outlet, useLocation, useNavigate } from "react-router-dom";
import { Outlet } from "react-router-dom";
import { TagsControl } from "./Subcomponents/Controls/TagsControl";
import { useSelectPosition, useSetMapClicked, useSetSelectPosition } from "./hooks/useSelectPosition";
import { useClusterRef, useSetClusterRef } from "./hooks/useClusterRef";
@ -20,6 +19,7 @@ import { FilterControl } from "./Subcomponents/Controls/FilterControl";
import { LayerControl } from "./Subcomponents/Controls/LayerControl";
import { useLayers } from "./hooks/useLayers";
import { useAddVisibleLayer } from "./hooks/useFilter";
import { GratitudeControl } from "./Subcomponents/Controls/GratitudeControl";
import { SelectPosition } from "./Subcomponents/SelectPosition";
// for refreshing map on resize (needs to be implemented)
@ -63,21 +63,13 @@ function UtopiaMap({
const selectNewItemPosition = useSelectPosition();
const setSelectNewItemPosition = useSetSelectPosition();
const location = useLocation();
const setClusterRef = useSetClusterRef();
const clusterRef = useClusterRef();
const setMapClicked = useSetMapClicked();
const [itemFormPopup, setItemFormPopup] = useState<ItemFormPopupProps | null>(null);
const [embedded, setEmbedded] = useState<boolean>(true)
useEffect(() => {
let params = new URLSearchParams(location.search);
let urlPosition = params.get("position");
let embedded = params.get("embedded");
embedded != "true" && setEmbedded(false)
}, [location]);
const layers = useLayers();
@ -113,6 +105,7 @@ function UtopiaMap({
{showFilterControl && <FilterControl />}
{/*todo: needed layer handling is located LayerControl*/}
{showLayerControl && <LayerControl></LayerControl>}
{<GratitudeControl/>}
</Control>
<TileLayer
maxZoom={19}

View File

@ -2,7 +2,7 @@ import { MapOverlayPage } from '../Templates'
import { useItems, useRemoveItem, useUpdateItem } from '../Map/hooks/useItems'
import { useLocation, useNavigate } from 'react-router-dom'
import { useEffect, useState } from 'react';
import { Item, Tag } from '../../types';
import { Item, ItemsApi, Tag } from '../../types';
import { useMap } from 'react-leaflet';
import { LatLng } from 'leaflet';
import { useHasUserPermission } from '../Map/hooks/usePermissions';
@ -17,7 +17,7 @@ import { SimpleView } from './Templates/SimpleView';
import { handleDelete, linkItem, unlinkItem } from './itemFunctions';
import { useTags } from '../Map/hooks/useTags';
export function ProfileView({ userType }: { userType: string }) {
export function ProfileView({ userType, attestationApi }: { userType: string , attestationApi?: ItemsApi<any>}) {
const [item, setItem] = useState<Item>()
const [updatePermission, setUpdatePermission] = useState<boolean>(false);
@ -40,6 +40,23 @@ export function ProfileView({ userType }: { userType: string }) {
const clusterRef = useClusterRef();
const leafletRefs = useLeafletRefs();
const [attestations, setAttestations] = useState<Array<any>>([]);
useEffect(() => {
if (attestationApi) {
attestationApi.getItems()
.then(value => {
console.log(value);
setAttestations(value);
})
.catch(error => {
console.error("Error fetching items:", error);
});
}
}, [attestationApi])
useEffect(() => {
const itemId = location.pathname.split("/")[2];
const item = items.find(i => i.id === itemId);
@ -140,7 +157,7 @@ export function ProfileView({ userType }: { userType: string }) {
}
{template == "tabs" &&
<TabsView setUrlParams={setUrlParams} item={item} loading={loading} offers={offers} needs={needs} relations={relations} updatePermission={updatePermission} linkItem={(id) => linkItem(id, item, updateItem)} unlinkItem={(id) => unlinkItem(id, item, updateItem)}/>
<TabsView userType={userType} attestations={attestations} setUrlParams={setUrlParams} item={item} loading={loading} offers={offers} needs={needs} relations={relations} updatePermission={updatePermission} linkItem={(id) => linkItem(id, item, updateItem)} unlinkItem={(id) => unlinkItem(id, item, updateItem)}/>
}
</>

View File

@ -17,6 +17,7 @@ export const TabsForm = ({ item, state, setState, updatePermission, linkItem, un
setActiveTab(id);
let params = new URLSearchParams(window.location.search);
params.set("tab", `${id}`);
const newUrl = location.pathname + "?" + params.toString();
window.history.pushState({}, '', newUrl);

View File

@ -5,9 +5,13 @@ import { ActionButton } from '../Subcomponents/ActionsButton'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useAddFilterTag } from '../../Map/hooks/useFilter'
import { Item, Tag } from 'utopia-ui/dist/types'
import { useNavigate } from 'react-router-dom'
import { Link, useNavigate } from 'react-router-dom'
import { useItems } from '../../Map/hooks/useItems'
import { useAssetApi } from '../../AppShell/hooks/useAssets'
import { timeAgo } from '../../../Utils/TimeAgo'
import { useAuth } from '../../Auth'
export const TabsView = ({ item, offers, needs, relations, updatePermission, loading, linkItem, unlinkItem, setUrlParams }: { item: Item, offers: Array<Tag>, needs: Array<Tag>, relations: Array<Item>, updatePermission: boolean, loading: boolean, linkItem: (id: string) => Promise<void>, unlinkItem: (id: string) => Promise<void> , setUrlParams: any}) => {
export const TabsView = ({ attestations, userType, item, offers, needs, relations, updatePermission, loading, linkItem, unlinkItem, setUrlParams }: { attestations: Array<any>, userType: string, item: Item, offers: Array<Tag>, needs: Array<Tag>, relations: Array<Item>, updatePermission: boolean, loading: boolean, linkItem: (id: string) => Promise<void>, unlinkItem: (id: string) => Promise<void>, setUrlParams: any }) => {
const addFilterTag = useAddFilterTag();
const [activeTab, setActiveTab] = useState<number>();
@ -15,12 +19,18 @@ export const TabsView = ({ item, offers, needs, relations, updatePermission, loa
const [addItemPopupType, setAddItemPopupType] = useState<string>("");
const items = useItems();
const assetsApi = useAssetApi();
const getUserProfile = (id: string) => {
return items.find(i => i.user_created.id === id && i.layer?.itemType.name === userType)
}
useEffect(() => {
scroll();
scroll();
}, [addItemPopupType])
function scroll() {
tabRef.current?.scrollIntoView();
tabRef.current?.scrollIntoView();
}
const tabRef = useRef<HTMLFormElement>(null);
@ -46,7 +56,7 @@ export const TabsView = ({ item, offers, needs, relations, updatePermission, loa
<div role="tablist" className="tw-tabs tw-tabs-lifted tw-mt-2 tw-mb-2 tw-px-6">
<input type="radio" name="my_tabs_2" role="tab"
className={`tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]`}
aria-label="Info" checked={activeTab == 1 && true}
aria-label="👤" checked={activeTab == 1 && true}
onChange={() => updateActiveTab(1)} />
<div role="tabpanel"
className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto fade tw-pt-2 tw-pb-4 tw-mb-4 tw-overflow-x-hidden">
@ -55,14 +65,63 @@ export const TabsView = ({ item, offers, needs, relations, updatePermission, loa
}
<TextView item={item} />
<div className='tw-h-4'></div>
<TextView item={item} itemTextField='contact'/>
<TextView item={item} itemTextField='contact' />
</div>
{item.layer?.itemType.questlog &&
<>
<input type="radio" name="my_tabs_2" role="tab"
className={`tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]`}
aria-label="❤️" checked={activeTab == 2 && true}
onChange={() => updateActiveTab(2)} />
<div role="tabpanel"
className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto fade tw-pt-2 tw-pb-4 tw-mb-4 tw-overflow-x-hidden">
<table className="sm:tw-table-sm md:tw-table-md">
<tbody>
{attestations
.filter(a => a.to.some(t => t.directus_users_id == item.user_created.id))
.sort((a, b) => new Date(b.date_created).getTime() - new Date(a.date_created).getTime())
.map((a, i) => (
<tr key={i}>
<td>
<div className={`tw-cursor-pointer tw-text-3xl tw-mask tw-mask-${a.shape} tw-p-3 tw-mr-2 tw-shadow-xl tw-bg-[${a.color}]`}>
{a.emoji}
</div>
</td>
<td>
<div className='tw-mr-2'><i>{a.text}</i></div>
</td>
<td>
<Link to={"/item/" + getUserProfile(a.user_created.id)?.id}>
<div className="flex items-center gap-3">
<div className="tw-avatar">
<div className="tw-mask tw-rounded-full h-8 w-8 tw-mr-2">
<img
src={assetsApi.url + getUserProfile(a.user_created.id)?.image}
alt="Avatar Tailwind CSS Component"
/>
</div>
</div>
<div>
<div className="font-bold">{getUserProfile(a.user_created.id)?.name}</div>
<div className="tw-text-xs opacity-50 tw-text-zinc-500">{timeAgo(a.date_created)}</div>
</div>
</div>
</Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
</>
}
{item.layer?.itemType.offers_and_needs &&
<>
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab tw-min-w-[10em] [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Offers & Needs" checked={activeTab == 3 && true} onChange={() => updateActiveTab(3)} />
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="♻️" checked={activeTab == 3 && true} onChange={() => updateActiveTab(3)} />
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-268px)] tw-overflow-y-auto fade tw-pt-4 tw-pb-1" >
<div className='tw-h-full'>
<div className='tw-grid tw-grid-cols-1'>
@ -100,7 +159,7 @@ export const TabsView = ({ item, offers, needs, relations, updatePermission, loa
{item.layer?.itemType.relations &&
<>
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Relations" checked={activeTab == 7 && true} onChange={() => updateActiveTab(7)} />
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="🔗" checked={activeTab == 7 && true} onChange={() => updateActiveTab(7)} />
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-h-[calc(100dvh-280px)] tw-overflow-y-auto tw-pt-4 tw-pb-1 -tw-mr-4 -tw-mb-4 tw-overflow-x-hidden">
<div className='tw-h-full'>
<div className='tw-grid tw-grid-cols-1 sm:tw-grid-cols-2 md:tw-grid-cols-1 lg:tw-grid-cols-1 xl:tw-grid-cols-1 2xl:tw-grid-cols-2 tw-pb-4'>

View File

@ -0,0 +1,108 @@
import { MapOverlayPage } from './MapOverlayPage'
import { useItems } from '../Map/hooks/useItems'
import { useAssetApi } from '../AppShell/hooks/useAssets'
import { EmojiPicker } from './EmojiPicker';
import { Link, useNavigate } from 'react-router-dom';
import { useRef, useState } from 'react';
import { Item, ItemsApi } from '../../types';
import { useEffect } from 'react';
import { toast } from 'react-toastify';
export const AttestationForm = ({api}:{api?:ItemsApi<any>}) => {
const items = useItems();
const assetsApi = useAssetApi();
const [users, setUsers] = useState<Array<Item>>();
const navigate = useNavigate();
useEffect(() => {
let params = new URLSearchParams(location.search);
let to_user_ids = params.get("to");
setUsers(items.filter(i => to_user_ids?.includes(i.id)))
}, [items, location])
const [inputValue, setInputValue] = useState('');
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
if (inputRef.current) {
inputRef.current.style.width = 'auto';
inputRef.current.style.width = `${inputRef.current.scrollWidth+20}px`;
}
}, [inputValue]);
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(event.target.value);
};
const sendAttestation = async () => {
const to : Array<any> = [];
users?.map(u => to.push({ directus_users_id: u.user_created.id }));
api?.createItem && toast.promise(
api.createItem({
text: inputValue,
emoji: selectedEmoji,
color: selectedColor,
shape: selectedShape,
to: to
}), {
pending: 'creating attestation ...',
success: 'Attestation created',
error: {
render({ data }) {
return `${data}`
},
},
})
.then( () => navigate("/item/" + items.find(i => i.user_created.id===to[0].directus_users_id && i.layer?.itemType.name==="player")?.id+"?tab=2")
)
}
const [selectedEmoji, setSelectedEmoji] = useState('select badge');
const [selectedShape, setSelectedShape] = useState('circle');
const [selectedColor, setSelectedColor] = useState('#fff0d6');
return (
<MapOverlayPage backdrop className='tw-h-fit tw-min-h-56 tw-w-96'>
<div className='tw-text-center tw-text-xl tw-font-bold'>Gratitude</div>
<div className='tw-text-center tw-text-base tw-text-gray-400'>to</div>
<div className='tw-flex tw-flex-row tw-justify-center tw-items-center tw-flex-wrap'>
{users && users.map((u, k) => (
<div key={k} className="tw-flex tw-items-center tw-space-x-3 tw-mx-2 tw-my-1">
{u.image ? <div className="tw-avatar">
<div className="tw-mask tw-mask-circle tw-w-8 tw-h-8">
<img src={assetsApi.url + u.image + "?width=40&heigth=40"} alt="Avatar" />
</div>
</div> :
<div className='tw-mask tw-mask-circle tw-text-xl md:tw-text-2xl tw-bg-slate-200 tw-rounded-full tw-w-8 tw-h-8'></div>}
<div>
<div className="tw-font-bold">{u.name}</div>
</div>
</div>
), ", ")}
</div>
<div className='tw-w-full'>
<div className='tw-flex tw-justify-center tw-items-center'>
<div className=' tw-flex tw-justify-center tw-items-center tw-w-28 tw-h-28 tw-m-4'>
<EmojiPicker selectedEmoji={selectedEmoji} selectedColor={selectedColor} selectedShape={selectedShape} setSelectedEmoji={setSelectedEmoji} setSelectedColor={setSelectedColor} setSelectedShape={setSelectedShape} />
</div>
</div>
<div className='tw-flex tw-justify-center tw-items-center'>
<input ref={inputRef}
value={inputValue}
onChange={handleChange}
type="text"
placeholder="... and say some words"
className="tw-input tw-min-w-0 tw-w-fit tw-resize-none tw-overflow-hidden tw-text-center " />
</div>
</div>
<div className='tw-w-full tw-grid tw-mt-4'><button onClick={sendAttestation} className="tw-btn tw-place-self-center tw-px-8">Next</button></div>
</MapOverlayPage>
)
}

View File

@ -0,0 +1,93 @@
import { useState } from 'react';
export const EmojiPicker = ({selectedEmoji, selectedColor, selectedShape, setSelectedEmoji, setSelectedColor, setSelectedShape}) => {
const [isOpen, setIsOpen] = useState(false);
const emojis = [
'❤️', '🙏', '👍', '🌻',, '✨', '☀️',
'🔥', '🪵', '💧', '🎶', '🎨','🍄',
'📝', '✉️', '🧩','💡', '🎓', '💬',
'🛠', '💻', '🕹', '🖨', '🚐', '🛒',
'⚽️', '🧵', '👀', '🌱',
'🏕', '💪', '🎁', '🏹',
'🥕', '🥇', '🥈', '🥉'];
const shapes = ["squircle", "circle", "hexagon-2"];
const colors = ["#FF99C8", "#fff0d6", "#FCF6BD", "#D0F4DE", "#A9DEF9", "#E4C1F9", "#de324c", "#f4895f", "#f8e16f", "#95cf92", "#369acc", "#9656a2"]
const toggleDropdown = () => {
setIsOpen(!isOpen);
};
const selectEmoji = (emoji) => {
setSelectedEmoji(emoji);
setIsOpen(false);
};
const selectShape = (shape) => {
setSelectedShape(shape);
setIsOpen(false);
};
const selectColor = (color) => {
setSelectedColor(color);
setIsOpen(false);
};
return (
<>
<div
onClick={toggleDropdown}
className={`tw-cursor-pointer ${selectedEmoji=="select badge" ? 'tw-text-sm !tw-p-9 tw-text-center ' : 'tw-text-6xl'} tw-mask tw-mask-${selectedShape} tw-p-6 tw-bg-[${selectedColor}]`}
>
{selectedEmoji}
</div>
{isOpen && (
<div className="tw-absolute tw-z-3000 tw-top-0 tw-left-1/2 tw-transform tw--translate-x-1/2 tw-mt-12 tw-bg-base-100 tw-rounded-2xl tw-shadow-lg tw-p-2 tw-w-full">
<div className='tw-grid tw-grid-cols-6 tw-gap-2 tw-pb-2'>
{emojis.map((emoji) => (
<button
key={emoji}
onClick={() => selectEmoji(emoji)}
className={`tw-cursor-pointer tw-text-2xl tw-p-2 hover:tw-bg-base-200 tw-rounded-md ${emoji == selectedEmoji && "tw-bg-base-300"}`}
>
{emoji}
</button>
))}
</div>
<hr />
<div className='tw-grid tw-grid-cols-3 tw-gap-2 tw-py-2'>
{shapes.map(shape => (
<div
key={shape}
className={`tw-cursor-pointer hover:tw-bg-base-200 tw-rounded-md tw-p-2 ${shape == selectedShape && "tw-bg-base-300"}`}
onClick={() => selectShape(shape)}>
<div className={`tw-h-12 tw-mask tw-mask-${shape} tw-bg-neutral-content`}></div>
</div>
))}
</div>
<hr />
<div className='tw-grid tw-grid-cols-6 tw-gap-2 tw-py-2 tw-px-6'>
{colors.map(color => (
<div
key={color}
className={`tw-cursor-pointer hover:tw-bg-base-200 tw-rounded-md tw-p-2 tw-flex tw-justify-center tw-items-center ${color == selectedColor && "tw-bg-base-300"}`}
onClick={() => selectColor(color)}>
<div className={`tw-h-8 tw-w-8 tw-rounded-full tw-bg-[${color}]`}></div>
</div>
))}
</div>
</div>
)}
</>
);
};

View File

@ -0,0 +1,55 @@
import { useState } from 'react'
import { MapOverlayPage } from './MapOverlayPage'
import { useItems } from '../Map/hooks/useItems'
import { useAssetApi } from '../AppShell/hooks/useAssets'
import { Link } from 'react-router-dom'
export const SelectUser = ({ userType }: { userType: string }) => {
const items = useItems();
const users = items.filter(i => i.layer?.itemType.name == userType)
const assetsApi = useAssetApi();
const [selectedUsers, setSelectedUsers] = useState<Array<string>>([]);
return (
<MapOverlayPage backdrop className='tw-h-3/4 tw-w-80'>
<div className='tw-text-center tw-text-xl tw-font-bold tw-mb-4'>Gratitude to ...</div>
{/* Team Member list in table format loaded constant */}
<div className="tw-overflow-x-auto tw-w-full fade">
<table className="tw-table tw-w-full">
<tbody>
{
users.map((u, k) => {
return (
<tr key={k}>
<td>
<input type="checkbox" onChange={() => setSelectedUsers(prev => [...prev, u.id])} className="tw-checkbox tw-checkbox-sm" />
</td>
<td>
<div className="tw-flex tw-items-center tw-space-x-3">
{u.image ? <div className="tw-avatar">
<div className="tw-mask tw-mask-circle tw-w-8 tw-h-8">
<img src={assetsApi.url + u.image+ "?width=40&heigth=40"} alt="Avatar" />
</div>
</div> :
<div className='tw-mask tw-mask-circle tw-text-xl md:tw-text-2xl tw-bg-slate-200 tw-rounded-full tw-w-8 tw-h-8'></div>}
<div>
<div className="tw-font-bold">{u.name}</div>
</div>
</div>
</td>
</tr>
)
})
}
</tbody>
</table>
</div>
<div className='tw-w-full tw-grid tw-mt-4'><Link className="tw-place-self-center " to={"/attestation-form"+"?to="+selectedUsers.map(u=> u,",")}><button className="tw-btn tw-px-8">Next</button></Link></div>
</MapOverlayPage>
)
}

View File

@ -1,5 +1,9 @@
import { AttestationForm } from './AttestationForm'
export {CardPage} from './CardPage'
export {TitleCard} from './TitleCard'
export {MapOverlayPage} from './MapOverlayPage'
export {MoonCalendar} from './MoonCalendar'
export {OverlayItemsIndexPage} from "./OverlayItemsIndexPage"
export {SelectUser} from "./SelectUser"
export {OverlayItemsIndexPage} from "./OverlayItemsIndexPage"
export {AttestationForm} from "./AttestationForm"

View File

@ -52,6 +52,10 @@
}
.placeholder-center::placeholder {
text-align: center;
}
.custom-file-upload {
cursor: pointer;
}

View File

@ -3,7 +3,7 @@ export {AppShell, Content, SideBar, Sitemap } from "./Components/AppShell"
export {AuthProvider, useAuth, LoginPage, SignupPage, RequestPasswordPage, SetNewPasswordPage} from "./Components/Auth"
export {UserSettings, ProfileView, ProfileForm} from './Components/Profile'
export {Quests, Modal} from './Components/Gaming'
export {TitleCard, CardPage, MapOverlayPage, OverlayItemsIndexPage, MoonCalendar } from './Components/Templates'
export {TitleCard, CardPage, MapOverlayPage, OverlayItemsIndexPage, MoonCalendar, SelectUser, AttestationForm } from './Components/Templates'
export {TextInput, TextAreaInput, SelectBox} from './Components/Input'
import "./index.css"

View File

@ -4,6 +4,25 @@ module.exports = {
"./src/**/*.{js,jsx,ts,tsx}",
"./node_modules/tw-elements/dist/js/**/*.js"
],
safelist: [
'tw-mask-squircle',
'tw-mask-circle',
'tw-mask-hexagon-2',
'tw-mask-decagon',
'tw-bg-[#FF99C8]',
'tw-bg-[#fff0d6]',
'tw-bg-[#FCF6BD]',
'tw-bg-[#D0F4DE]',
'tw-bg-[#A9DEF9]',
'tw-bg-[#E4C1F9]',
'tw-bg-[#de324c]',
'tw-bg-[#f4895f]',
'tw-bg-[#f8e16f]',
'tw-bg-[#95cf92]',
'tw-bg-[#369acc]',
'tw-bg-[#9656a2]',
],
theme: {
extend: {
zIndex: {
@ -31,7 +50,7 @@ module.exports = {
'sans': ["Helvetica", "sans-serif", 'Roboto'],
},
fontSize: {
'map': "13px"
'map': "13px"
},
lineHeight: {
'map': "1.4em"
@ -54,17 +73,18 @@ module.exports = {
],
daisyui: {
themes: ["light", "dark", "cupcake", "retro", "cyberpunk", "aqua",
{
docutopia: {
"primary": "#8e00ff",
"secondary": "#00bb7a",
"accent": "#006aff",
"neutral": "#231502",
"base-content": "#ffad6b",
"base-100": "#440844",
},
},]
{
docutopia: {
"primary": "#8e00ff",
"secondary": "#00bb7a",
"accent": "#006aff",
"neutral": "#231502",
"base-content": "#ffad6b",
"base-100": "#440844",
},
},]
},
prefix: 'tw-',
content: ['./src/**/*.{js,jsx,ts,tsx}'],
}
}