new form and form tweaks
This commit is contained in:
		@@ -30,7 +30,9 @@ export const MainLayout = () => {
 | 
			
		||||
          <Switch>
 | 
			
		||||
            <Route path="/sign-up" component={NewUser} />
 | 
			
		||||
            <Route path="/login" component={Login} />
 | 
			
		||||
            <div>loading...</div>
 | 
			
		||||
            <Route path="/">
 | 
			
		||||
              <div>loading...</div>
 | 
			
		||||
            </Route>
 | 
			
		||||
          </Switch>
 | 
			
		||||
        ) : (
 | 
			
		||||
          <Switch>
 | 
			
		||||
 
 | 
			
		||||
@@ -6,11 +6,6 @@
 | 
			
		||||
 | 
			
		||||
  align-items: center;
 | 
			
		||||
 | 
			
		||||
  h1 {
 | 
			
		||||
    margin-top: 2.5vmin;
 | 
			
		||||
    margin-bottom: 1vmin;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  main {
 | 
			
		||||
    height: 100%;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ type Props = {
 | 
			
		||||
type AppContextInterface = {
 | 
			
		||||
  get: <T>(path: string) => Promise<T>
 | 
			
		||||
  patch: <T>(path: string, body: Partial<T>) => Promise<T>
 | 
			
		||||
  post: <T, R = T>(path: string, body: Partial<T>) => Promise<R>
 | 
			
		||||
  post: <T, R = T>(path: string, body: Partial<T>) => Promise<R | null>
 | 
			
		||||
  create: <T>(path: string, body: Partial<T>) => Promise<T>
 | 
			
		||||
  destroy: (path: string) => Promise<string>
 | 
			
		||||
  baseURL?: string
 | 
			
		||||
@@ -39,8 +39,12 @@ export const AppContextProvider = ({ children, baseURL }: Props) => {
 | 
			
		||||
    return res.data
 | 
			
		||||
  }
 | 
			
		||||
  async function post<T, R = T>(path: string, body: Partial<T>) {
 | 
			
		||||
    const res = await api.post<T, AxiosResponse<R>>(path, body)
 | 
			
		||||
    return res.data
 | 
			
		||||
    try {
 | 
			
		||||
      const res = await api.post<T, AxiosResponse<R>>(path, body)
 | 
			
		||||
      return res.data
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      return null
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  async function create<T>(path: string, body: Partial<T>) {
 | 
			
		||||
    // unauthed POST
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,30 @@
 | 
			
		||||
@import '../../scss/variables.scss';
 | 
			
		||||
 | 
			
		||||
.dank-form {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  padding: 3ch;
 | 
			
		||||
 | 
			
		||||
  input {
 | 
			
		||||
    border-radius: 0.25rem;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    font-size: 2rem;
 | 
			
		||||
    border: 1px solid $color-grey;
 | 
			
		||||
 | 
			
		||||
    &:focus {
 | 
			
		||||
      outline: 2px solid $color-primary;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  button {
 | 
			
		||||
    width: 40%;
 | 
			
		||||
    font-size: 2rem;
 | 
			
		||||
    border-radius: 0.25rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  label {
 | 
			
		||||
    margin: 0.5ch;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    font-size: 1.5rem;
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    justify-content: space-between;
 | 
			
		||||
 | 
			
		||||
@@ -13,8 +32,4 @@
 | 
			
		||||
      margin-left: 2ch;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  button {
 | 
			
		||||
    margin: 4ch 1ch;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import { FormItemProps } from 'antd'
 | 
			
		||||
import AntFormItem from 'antd/lib/form/FormItem'
 | 
			
		||||
import './style.scss'
 | 
			
		||||
 | 
			
		||||
type Props = FormItemProps
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								frontend/src/elements/FormItem/style.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								frontend/src/elements/FormItem/style.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
.dank-form-item {
 | 
			
		||||
  label {
 | 
			
		||||
    color: white;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,9 @@
 | 
			
		||||
import { InputNumber as AntInputNumber, InputNumberProps } from 'antd'
 | 
			
		||||
 | 
			
		||||
import './style.scss'
 | 
			
		||||
 | 
			
		||||
type Props = InputNumberProps
 | 
			
		||||
 | 
			
		||||
export const InputNumber = (props: Props) => {
 | 
			
		||||
  return <AntInputNumber {...props} />
 | 
			
		||||
  return <AntInputNumber className="dank-input-number" {...props} />
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								frontend/src/elements/InputNumber/style.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								frontend/src/elements/InputNumber/style.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
.ant-input-number {
 | 
			
		||||
  display: grid;
 | 
			
		||||
  grid-template: 1fr / 1fr;
 | 
			
		||||
 | 
			
		||||
  div {
 | 
			
		||||
    grid-area: 1/1/2/2;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-handler {
 | 
			
		||||
    &-wrap {
 | 
			
		||||
      z-index: 2;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      pointer-events: none;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: row;
 | 
			
		||||
      justify-content: flex-end;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &-up,
 | 
			
		||||
    &-down {
 | 
			
		||||
      pointer-events: all;
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
      margin: auto 0.5rem auto 0;
 | 
			
		||||
      svg {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-input-wrap {
 | 
			
		||||
    z-index: 1;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								frontend/src/forms/TransactionForm.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								frontend/src/forms/TransactionForm.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
import { useForm } from 'antd/lib/form/Form'
 | 
			
		||||
import { Button } from '../elements/Button'
 | 
			
		||||
import { Form } from '../elements/Form'
 | 
			
		||||
import { FormItem } from '../elements/FormItem'
 | 
			
		||||
import { Input } from '../elements/Input'
 | 
			
		||||
import { InputNumber } from '../elements/InputNumber'
 | 
			
		||||
import {
 | 
			
		||||
  useCreateTransaction,
 | 
			
		||||
  NewTransaction,
 | 
			
		||||
} from '../hooks/create/useCreateTransaction'
 | 
			
		||||
import { DankFormProps } from '../layout/Modal'
 | 
			
		||||
import { Row } from '../layout/Row'
 | 
			
		||||
 | 
			
		||||
type Props = DankFormProps & {
 | 
			
		||||
  stackId: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const TransactionForm = ({ stackId, onSave, onCancel }: Props) => {
 | 
			
		||||
  const [form] = useForm<NewTransaction>()
 | 
			
		||||
  const create = useCreateTransaction()
 | 
			
		||||
 | 
			
		||||
  const handleFinish = async (tx: NewTransaction) => {
 | 
			
		||||
    console.log('transaction', tx)
 | 
			
		||||
    const res = await create(tx)
 | 
			
		||||
 | 
			
		||||
    if (!res) {
 | 
			
		||||
      console.log("couldn't create transaction")
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onSave?.()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Form
 | 
			
		||||
      form={form}
 | 
			
		||||
      onFinish={handleFinish}
 | 
			
		||||
      initialValues={{ stack: stackId }}
 | 
			
		||||
    >
 | 
			
		||||
      <h1>New Transaction</h1>
 | 
			
		||||
      <FormItem label="Amount" name="amount">
 | 
			
		||||
        <InputNumber />
 | 
			
		||||
      </FormItem>
 | 
			
		||||
      <FormItem label="Details" name="amount">
 | 
			
		||||
        <Input />
 | 
			
		||||
      </FormItem>
 | 
			
		||||
      <Row>
 | 
			
		||||
        <Button onClick={onCancel}>Cancel</Button>
 | 
			
		||||
        <Button htmlType="submit">Save</Button>
 | 
			
		||||
      </Row>
 | 
			
		||||
    </Form>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
@@ -4,6 +4,6 @@ import { Account } from '../../types'
 | 
			
		||||
export const useCreateAccount = () => {
 | 
			
		||||
  const api = useAppContext()
 | 
			
		||||
 | 
			
		||||
  return (body: Omit<Account, 'id'>): Promise<Account> =>
 | 
			
		||||
  return (body: Omit<Account, 'id'>): Promise<Account | null> =>
 | 
			
		||||
    api.post<Account>('/accounts', body)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,6 @@ import { Stack } from '../../types'
 | 
			
		||||
export const useCreateStack = () => {
 | 
			
		||||
  const api = useAppContext()
 | 
			
		||||
 | 
			
		||||
  return (body: Omit<Stack, 'id'>): Promise<Stack> =>
 | 
			
		||||
  return (body: Omit<Stack, 'id'>): Promise<Stack | null> =>
 | 
			
		||||
    api.post<Stack>('/stacks', body)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,11 @@
 | 
			
		||||
import { useAppContext } from '../../contexts/AppContext'
 | 
			
		||||
import { Transaction } from '../../types'
 | 
			
		||||
 | 
			
		||||
export type NewTransaction = Omit<Transaction, 'id'>
 | 
			
		||||
 | 
			
		||||
export const useCreateTransaction = () => {
 | 
			
		||||
  const api = useAppContext()
 | 
			
		||||
 | 
			
		||||
  return (body: Omit<Transaction, 'id'>): Promise<Transaction> =>
 | 
			
		||||
    api.post<Transaction>('/transactions', body)
 | 
			
		||||
  return (body: NewTransaction): Promise<Transaction | null> =>
 | 
			
		||||
    api.post<Transaction>('/transactions/', body)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,6 @@ import { User } from '../../types'
 | 
			
		||||
export const useCreateUser = () => {
 | 
			
		||||
  const api = useAppContext()
 | 
			
		||||
 | 
			
		||||
  return (body: Omit<User, 'id'>): Promise<User> =>
 | 
			
		||||
  return (body: Omit<User, 'id'>): Promise<User | null> =>
 | 
			
		||||
    api.post<User>('/users', body)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
import { Transaction } from '../../types'
 | 
			
		||||
import { useGet } from '../util/useGet'
 | 
			
		||||
 | 
			
		||||
export const useTransactions = () => useGet<Transaction[]>(`/transactions/`)
 | 
			
		||||
export const useTransactions = () =>
 | 
			
		||||
  useGet<Transaction[]>(`/transactions/`, { mode: 'list' })
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,16 @@
 | 
			
		||||
import { ModalProps } from 'antd'
 | 
			
		||||
import { ReactNode } from 'react'
 | 
			
		||||
import { ReactElement, cloneElement } from 'react'
 | 
			
		||||
import './style.scss'
 | 
			
		||||
 | 
			
		||||
type Props = ModalProps & { children: ReactNode }
 | 
			
		||||
type Props = ModalProps & { children: ReactElement }
 | 
			
		||||
 | 
			
		||||
export const Modal = ({ children, ...props }: Props) => {
 | 
			
		||||
  return <div className="dank-modal">{children}</div>
 | 
			
		||||
export type DankFormProps = {
 | 
			
		||||
  onSave?: () => void
 | 
			
		||||
  onCancel?: () => void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const Modal = ({ children, visible }: Props) => {
 | 
			
		||||
  const el = cloneElement(children, (props: DankFormProps) => ({ ...props }))
 | 
			
		||||
 | 
			
		||||
  return visible ? <div className="dank-modal">{el}</div> : null
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,20 @@
 | 
			
		||||
@import '../../scss/variables.scss';
 | 
			
		||||
 | 
			
		||||
.dank-modal {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  width: 70%;
 | 
			
		||||
  height: 70%;
 | 
			
		||||
  background-color: transparentize(#222, 0.07);
 | 
			
		||||
  border-radius: 1rem;
 | 
			
		||||
  padding: 1rem;
 | 
			
		||||
  margin: auto;
 | 
			
		||||
  border: 1px solid $color-grey;
 | 
			
		||||
 | 
			
		||||
  h3 {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
  h1,
 | 
			
		||||
  h2,
 | 
			
		||||
  h3,
 | 
			
		||||
  h4,
 | 
			
		||||
  h5 {
 | 
			
		||||
    color: $color-light;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								frontend/src/layout/Row/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								frontend/src/layout/Row/index.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
import React from 'react'
 | 
			
		||||
import './style.scss'
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
  children: React.ReactNode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const Row = ({ children }: Props) => {
 | 
			
		||||
  return <div className="dank-row">{children}</div>
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								frontend/src/layout/Row/style.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								frontend/src/layout/Row/style.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
.dank-row {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row;
 | 
			
		||||
  justify-content: space-between;
 | 
			
		||||
  margin: 1rem 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -11,7 +11,7 @@ export const Dashboard = () => {
 | 
			
		||||
    <Page>
 | 
			
		||||
      <h1>Remaining Balances</h1>
 | 
			
		||||
      {accounts.data?.map((account) => (
 | 
			
		||||
        <div className="account-overview">
 | 
			
		||||
        <div key={account.id} className="account-overview">
 | 
			
		||||
          <h3>{account.name}</h3>
 | 
			
		||||
          <div className="funds">
 | 
			
		||||
            {account.stacks.map((stack) => (
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@
 | 
			
		||||
  border: 1px solid $color-grey;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  margin: 1rem 0;
 | 
			
		||||
  padding: 1rem;
 | 
			
		||||
  background: $color-alt;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,4 +3,5 @@ $color-alt: #c9d8b6;
 | 
			
		||||
$color-light: #f1ecc3;
 | 
			
		||||
$color-white: #fff;
 | 
			
		||||
$color-grey: #515e63;
 | 
			
		||||
$color-black: #111;
 | 
			
		||||
$color-dark: #333;
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ export type Stack = {
 | 
			
		||||
  account: string //'38485982-87f3-4a11-a963-2202983809e3'
 | 
			
		||||
  name: string // 'House Fund'
 | 
			
		||||
  details: string //'buy furniture'
 | 
			
		||||
  amount: number // '200.00'
 | 
			
		||||
  amount: string // number // '200.00'
 | 
			
		||||
  transactions: Transaction[]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -36,7 +36,7 @@ export type Transaction = {
 | 
			
		||||
  id: string
 | 
			
		||||
  stack: string // '0058cece-3ff3-4ee1-b71d-075a0bc73bc0'
 | 
			
		||||
  details: string // 'by ghetto couch off Kijiji'
 | 
			
		||||
  amount: number // '30.44'
 | 
			
		||||
  amount: string // number // '30.44'
 | 
			
		||||
  created_at: string // '2021-04-15T00:02:45.096071Z'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,10 @@
 | 
			
		||||
import { Link } from 'react-router-dom'
 | 
			
		||||
import { message } from 'antd'
 | 
			
		||||
import './style.scss'
 | 
			
		||||
import { Button } from '../../elements/Button'
 | 
			
		||||
import { useAccounts } from '../../hooks/getMany/useAccounts'
 | 
			
		||||
 | 
			
		||||
import './style.scss'
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
  selectProfile: (id: string) => void
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,40 +1,47 @@
 | 
			
		||||
import { Stack } from '../../types'
 | 
			
		||||
import './style.scss'
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
import { useState } from 'react'
 | 
			
		||||
import { Modal } from '../../layout/Modal'
 | 
			
		||||
import { TransactionForm } from '../../forms/TransactionForm'
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
  stack: Stack
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const FundBar = ({ stack }: Props) => {
 | 
			
		||||
  const amount = _.sumBy(stack.transactions, 'amount')
 | 
			
		||||
  console.log('amount', stack.id, amount)
 | 
			
		||||
  const max = stack.amount
 | 
			
		||||
  const amount = _.sumBy(stack.transactions, (tx) => parseFloat(tx.amount))
 | 
			
		||||
  const max = parseFloat(stack.amount)
 | 
			
		||||
  const current = max - amount
 | 
			
		||||
  const percent = Math.max(current / max, 0)
 | 
			
		||||
  const hue = percent * 120
 | 
			
		||||
  const u = Math.max(current / max, 0)
 | 
			
		||||
 | 
			
		||||
  const [newTx, setNewTx] = useState(false)
 | 
			
		||||
 | 
			
		||||
  const addTransaction = () => {
 | 
			
		||||
    console.log(`adding transaction to => ${stack.name}`)
 | 
			
		||||
    setNewTx(true)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="fundbar">
 | 
			
		||||
      <div
 | 
			
		||||
        className={`back`}
 | 
			
		||||
        onClick={() => console.log(`adding transaction to => ${stack.name}`)}
 | 
			
		||||
      ></div>
 | 
			
		||||
      <div
 | 
			
		||||
        className={`front`}
 | 
			
		||||
        style={{
 | 
			
		||||
          background: `hsl(${hue}, 100%, 50%)`,
 | 
			
		||||
          height: `${percent * 40 + 10}vmin`,
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <h3>{stack.name}</h3>
 | 
			
		||||
    <>
 | 
			
		||||
      <div className="fundbar">
 | 
			
		||||
        <div className="back" onClick={addTransaction}>
 | 
			
		||||
          <h3>{stack.name}</h3>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div
 | 
			
		||||
          className="front"
 | 
			
		||||
          style={{
 | 
			
		||||
            background: `hsl(${u * 120}, 100%, 50%)`,
 | 
			
		||||
            height: `${u * 100}%`,
 | 
			
		||||
          }}
 | 
			
		||||
        ></div>
 | 
			
		||||
        <div className="totals">
 | 
			
		||||
          ${Math.floor(current)} / ${max}
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div
 | 
			
		||||
        className={`totals`}
 | 
			
		||||
        style={{ color: `hsl(0, 0%, ${Math.abs(1 - percent) * 100}%)` }}
 | 
			
		||||
      >
 | 
			
		||||
        ${Math.floor(current)} / ${max}
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
      <Modal visible={newTx} onCancel={() => setNewTx(false)}>
 | 
			
		||||
        <TransactionForm stackId={stack.id} />
 | 
			
		||||
      </Modal>
 | 
			
		||||
    </>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
  margin: 1rem;
 | 
			
		||||
  display: grid;
 | 
			
		||||
  grid-template: 1fr / 1fr;
 | 
			
		||||
  height: 20vh;
 | 
			
		||||
 | 
			
		||||
  .totals {
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
@@ -18,17 +19,20 @@
 | 
			
		||||
 | 
			
		||||
  .front {
 | 
			
		||||
    grid-area: 1/1/2/2;
 | 
			
		||||
    margin: auto auto 0;
 | 
			
		||||
    border-radius: 1ch;
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
    transition: all 0.2s ease-out;
 | 
			
		||||
    border: 2px solid $color-dark;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    padding: 2ch;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    min-height: 1rem;
 | 
			
		||||
    text-shadow: 2px 2px #2223, -1px -1px #fffa;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .back {
 | 
			
		||||
    padding: 0.25rem;
 | 
			
		||||
    grid-area: 1/1/2/2;
 | 
			
		||||
    background: #222;
 | 
			
		||||
    border-radius: 1ch;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user